LeetCode 补拙笔记
0. 前言
- 日期:2026.06.07
- 题目:49. 字母异位词分组
- 难度:中等
- 标签:字符串、哈希表、排序
1. 题目理解
问题描述 :
给定一个字符串数组,将字母异位词组合在一起。字母异位词指的是由相同字母以不同顺序排列而成的单词。
示例:
输入:
strs = ["eat","tea","tan","ate","nat","bat"]输出:
[["bat"],["nat","tan"],["ate","eat","tea"]]
2. 解题思路
核心观察
- 字母异位词的核心特征:字符相同,顺序不同。
- 排序后,异位词会变成同一个字符串(如
eat和tea排序后都是aet),因此可以用排序后的字符串作为哈希表的键。
算法步骤
- 遍历所有字符串;
- 对每个字符串排序,生成唯一键;
- 以排序后的字符串为键,将原字符串加入哈希表对应的列表;
- 最后取出哈希表中所有的值,即为分组结果。
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(nklogk)O(nk\log k)O(nklogk),其中 nnn 是字符串数量,kkk 是字符串平均长度。每个字符串排序的时间复杂度为 O(klogk)O(k\log k)O(klogk)。
- 空间复杂度 :O(nk)O(nk)O(nk),哈希表存储所有字符串,总空间为 nnn 个长度为 kkk 的字符串。
6. 总结
- 核心:排序+哈希表,用排序后的字符串作为异位词的唯一标识。
- 优化点:使用
computeIfAbsent简化哈希表操作,减少分支判断;懒加载方式延迟初始化结果列表,提升性能。 - 关键技巧:异位词分组的核心是找到一个稳定的键,排序是最直接的实现方式。