LeetCode 补拙笔记 日期:2026.06.07 题目:49. 字母异位词分组

LeetCode 补拙笔记

0. 前言

  • 日期:2026.06.07
  • 题目:49. 字母异位词分组
  • 难度:中等
  • 标签:字符串、哈希表、排序

1. 题目理解

问题描述

给定一个字符串数组,将字母异位词组合在一起。字母异位词指的是由相同字母以不同顺序排列而成的单词。

示例

输入:strs = ["eat","tea","tan","ate","nat","bat"]

输出:[["bat"],["nat","tan"],["ate","eat","tea"]]

2. 解题思路

核心观察

  • 字母异位词的核心特征:字符相同,顺序不同
  • 排序后,异位词会变成同一个字符串(如 eattea 排序后都是 aet),因此可以用排序后的字符串作为哈希表的键。

算法步骤

  1. 遍历所有字符串;
  2. 对每个字符串排序,生成唯一键;
  3. 以排序后的字符串为键,将原字符串加入哈希表对应的列表;
  4. 最后取出哈希表中所有的值,即为分组结果。

3. 代码实现

java 复制代码
package lc0_lc99.lc49;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        int index =0;
        List<List<String>> res = new ArrayList<>();
        HashMap<String, Integer> map = new HashMap<>();
        for (int i = 0; i < strs.length; i++) {
            String s = strs[i];
            int n = method1(s, map);
            if (n != -1) {
                res.get(n).add(s);
            }
            else {
                ArrayList<String > ss = new ArrayList<>();
                ss.add(s);
                res.add(ss);
                char[] chars = s.toCharArray();
                Arrays.sort(chars);
                String s1 = String.valueOf(chars);
                map.put(s1,index++);
            }
        }

        return res;
    }

    private int method1(String s, HashMap<String, Integer> map) {
        char[] chars = s.toCharArray();
        Arrays.sort(chars);
        String s1 = String.valueOf(chars);
        if (map.containsKey(s1)) {
            return map.get(s1);
        }
        return -1;
    }
}

4. 代码优化说明

java 复制代码
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
    // 使用匿名内部类继承AbstractList实现懒加载
    return new AbstractList<>() {
        List<List<String>> list = null;

        // 懒加载初始化方法,仅在首次访问时执行
        private void init() {
            if (list != null) {
                return;
            }
            Map<String, List<String>> map = new HashMap<>();
            for (String str : strs) {
                // 排序生成异位词的统一key
                char[] chars = str.toCharArray();
                Arrays.sort(chars);
                String key = new String(chars);
                // computeIfAbsent:key不存在时创建新列表,存在时直接返回列表
                map.computeIfAbsent(key, k -> new ArrayList<>()).add(str);
            }
            list = new ArrayList<>(map.values());
        }

        // 重写get方法,访问前触发初始化
        @Override
        public List<String> get(int index) {
            init();
            return list.get(index);
        }

        // 重写size方法,访问前触发初始化
        @Override
        public int size() {
            init();
            return list.size();
        }
    };
}
}

5. 复杂度分析

  • 时间复杂度 :O(nklog⁡k)O(nk\log k)O(nklogk),其中 nnn 是字符串数量,kkk 是字符串平均长度。每个字符串排序的时间复杂度为 O(klog⁡k)O(k\log k)O(klogk)。
  • 空间复杂度 :O(nk)O(nk)O(nk),哈希表存储所有字符串,总空间为 nnn 个长度为 kkk 的字符串。

6. 总结

  • 核心:排序+哈希表,用排序后的字符串作为异位词的唯一标识。
  • 优化点:使用 computeIfAbsent 简化哈希表操作,减少分支判断;懒加载方式延迟初始化结果列表,提升性能。
  • 关键技巧:异位词分组的核心是找到一个稳定的键,排序是最直接的实现方式。
相关推荐
血色橄榄枝13 小时前
基于用户注册信息的关键词检测挑战赛「Datawhale AI 夏令营」
人工智能·算法·机器学习
c2385614 小时前
第二篇:《测试指挥官:可视化单题自测框架(含 assert 实操)》
java·数据库·c++·算法·安全性测试
六点_dn15 小时前
Linux学习笔记-printf命令
linux·运维·算法
遥感知识服务16 小时前
Sentinel-1 + DEM + FwDET + 随机森林:从快速水深初估到多因子误差修正
算法·随机森林·sentinel
来一碗刘肉面16 小时前
顺序表与链表的比较
数据结构·算法·链表
alphaTao16 小时前
LeetCode 每日一题 2026/7/13-2026/7/19
算法·leetcode
nnerddboy17 小时前
脑电信号处理实战 03 | 运动想象脑机接口入门:ERD/ERS、CSP 空间滤波与左右拳想象解码
算法·信号处理
QN1幻化引擎18 小时前
Dalin L — 我造了一门支持中文编程的语言,完整移植到 Rust 了
人工智能·算法·机器学习
Rainy Blue88318 小时前
C转C++速成
c语言·c++·算法
txzrxz18 小时前
二分图详解
数据结构·c++·算法·图论·深度优先搜索·二分图染色