Skip to content

题目链接 · 灵神原题解(署名来源)

题意解读

如果两个字符串从小到大排序后相等,那么两个字符串就互为字母异位词,否则不是。

例如 aab,aba,baa 排序后都是 aab,所以 aab,aba,baa 互为字母异位词。

示例 1 是怎么算的?

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

每个字符串各自排序,得到 aet,aet,ant,aet,ant,abt

把排序后相同的字符串分到同一组:

  • 排序后是 aet 的字符串,排序前是 eat,tea,ate
  • 排序后是 ant 的字符串,排序前是 tan,nat
  • 排序后是 abt 的字符串,排序前是 bat

因此,示例 1 返回的二维列表中,包含三个列表,分别为

  • [eat,tea,ate]
  • [tan,nat]
  • [bat]

三个列表的顺序随意。

算法

用哈希表分组,把排序后的字符串当作哈希表的 key,排序前的字符串加到对应的列表中(哈希表的 value)。

最后把哈希表的所有 value 加到一个列表中返回。

python
class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        d = {}  # 用 defaultdict 的写法见【Python3 写法二】
        for s in strs:
            sorted_s = ''.join(sorted(s))  # 把 s 排序,作为 dict 的 key
            if sorted_s not in d:  # 首次遇到 sorted_s
                d[sorted_s] = []  # 创建列表
            d[sorted_s].append(s)  # 排序后相同的字符串,保存到同一组中
        return list(d.values())  # 哈希表的所有 value 就是分组结果
cpp
// C++ 版待补充
python
class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        d = defaultdict(list)  # 如果 key 不在字典中,defaultdict 会自动创建一个空列表作为 value
        for s in strs:
            sorted_s = ''.join(sorted(s))  # 把 s 排序,作为 defaultdict 的 key
            d[sorted_s].append(s)  # 排序后相同的字符串,保存到同一组中
        return list(d.values())  # 哈希表的所有 value 就是分组结果
cpp
// C++ 版待补充
cpp
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string, vector<string>> m;
        for (string& s : strs) {
            string sorted_s = s;
            ranges::sort(sorted_s); // 把 s 排序,作为哈希表的 key
            m[sorted_s].push_back(s); // 排序后相同的字符串,保存到同一组中
        }

        vector<vector<string>> ans;
        ans.reserve(m.size()); // 预分配空间
        for (auto& [_, value] : m) {
            ans.push_back(value); // 哈希表的所有 value 就是分组结果
        }
        return ans;
    }
};

复杂度分析

  • 时间复杂度:O(nmlogm),其中 nstrs 的长度,mstrs[i] 的长度。每个字符串排序需要 O(mlogm) 的时间,有 n 个字符串,所以总的时间复杂度为 O(nmlogm)
  • 空间复杂度:O(nm)

分类题单

如何科学刷题?

  1. 滑动窗口与双指针(定长/不定长/单序列/双序列/三指针/分组循环)
  2. 二分算法(二分答案/最小化最大值/最大化最小值/第K小)
  3. 单调栈(基础/矩形面积/贡献法/最小字典序)
  4. 网格图(DFS/BFS/综合应用)
  5. 位运算(基础/性质/拆位/试填/恒等式/思维)
  6. 图论算法(DFS/BFS/拓扑排序/基环树/最短路/最小生成树/网络流)
  7. 动态规划(入门/背包/划分/状态机/区间/状压/数位/数据结构优化/树形/博弈/概率期望)
  8. 常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树)
  9. 数学算法(数论/组合/概率期望/博弈/计算几何/随机算法)
  10. 贪心与思维(基本贪心策略/反悔/区间/字典序/数学/思维/脑筋急转弯/构造)
  11. 链表、树与回溯(前后指针/快慢指针/DFS/BFS/直径/LCA)
  12. 字符串(KMP/Z函数/Manacher/字符串哈希/AC自动机/后缀数组/子序列自动机)

我的题解精选(已分类)

欢迎关注 B站@灵茶山艾府

本文整理自灵茶山艾府(endlesscheng)的公开内容,仅供个人学习使用

本站仅供个人学习使用,请勿外传