← 返回题目列表

如何用哈希表对字母异位词分组?

高频 中等 第 10 / 29 题 更新于 2026/07/29
哈希表字符串字母异位词

简化版

字母异位词分组的关键是给同组字符串生成相同 key。常见 key 有排序后的字符串,或 26 个字母计数数组序列化后的字符串。用 Map<key, List<String>> 聚合即可。

详细版

字母异位词是字符种类和次数完全相同、顺序不同的字符串。例如 eatteaate 排序后都是 aet,所以可以作为同一个哈希 key。

List<List<String>> groupAnagrams(String[] strs) {
    Map<String, List<String>> groups = new HashMap<>();
    for (String s : strs) {
        char[] chars = s.toCharArray();
        Arrays.sort(chars);
        String key = new String(chars);
        groups.computeIfAbsent(key, k -> new ArrayList<>()).add(s);
    }
    return new ArrayList<>(groups.values());
}

如果字符串很长且只含小写字母,也可以用 26 位计数生成 key,避免每个字符串排序。

完整版教学

一、分组题的核心是“同类同 key”

哈希表分组类题目,本质是为每个对象提取一个“归一化 key”。只要两个字符串是字母异位词,就必须得到相同 key;不是异位词,就尽量得到不同 key。然后用哈希表把相同 key 的字符串放进同一个列表。

例如 ["eat","tea","tan","ate","nat","bat"],排序 key 分别是 aet,aet,ant,aet,ant,abt,最终形成三组。

二、排序 key 为什么可行

字母异位词只改变字符顺序,不改变字符多重集合。排序会把同一组字符排列成唯一顺序,所以异位词排序后一定相同。反过来,如果排序后相同,说明字符和次数完全一致,也就是异位词。

eat -> aet
tea -> aet
ate -> aet
tan -> ant
nat -> ant

排序 key 的优点是简单稳妥,适合面试第一版。

三、计数 key 如何优化

如果题目限定只含小写英文字母,可以统计 26 个字母出现次数,再把计数数组序列化成 key。例如 abb 的计数是 a:1,b:2,可以写成 #1#2#0...

int[] count = new int[26];
for (char c : s.toCharArray()) count[c - 'a']++;
StringBuilder key = new StringBuilder();
for (int x : count) key.append('#').append(x);

计数 key 生成是 O(L),排序 key 是 O(L log L)。当字符串很长、字符集固定时,计数更合适。

四、为什么 key 不能简单相加或相乘

有人会把字符编码相加作为 key,例如 abba 和相同,这是对的;但 adbc 的字符和也可能相同,这就会把不同组误合并。乘质数也要处理溢出问题,不如排序或计数稳定。

key 方案正确性代价
排序字符串稳定正确O(L log L)
字母计数字符集固定时稳定正确O(L + C)
字符和会碰撞不推荐

分组题最怕 key 不唯一导致错误合并。

五、复杂度怎么分析

设有 n 个字符串,平均长度为 L。排序 key 的时间复杂度是 O(n * L log L),空间复杂度是 O(n * L) 用于结果和 key。计数 key 在固定 26 字母下是 O(n * (L + 26)),通常写作 O(nL)。

哈希表本身负责按 key 聚合,computeIfAbsent 只是减少样板代码,不改变算法本质。

六、常见误区与追问

记忆钩子:异位词分组先别急着分组,先问“什么特征能让同组字符串变成同一个 key”。

  • 误区:用字符编码求和当 key。 不同字符串可能和相同,会错误分组。
  • 误区:计数 key 直接用数组对象。 Java 数组默认按引用比较,必须序列化或包装成可比较对象。
  • 误区:忽略字符集。 若包含 Unicode 或大小写,26 位小写计数不再适用。
  • 追问:排序和计数怎么选? 排序通用简单,计数在固定小字符集下更快。
  • 追问:分组结果顺序要保证吗? 普通 HashMap 不保证顺序;若题目要求稳定顺序,可用 LinkedHashMap。
  • 追问:为什么哈希表适合分组? key 相同的对象能平均 O(1) 定位到同一个桶对应的列表。

七、加强记忆

字母异位词分组的套路是“归一化 key + Map 聚合”。排序 key 把同一组字符排成同一形态;计数 key 把字符多重集合写成固定签名。只要 key 设计正确,分组就变成简单的 Map<key, List>