题目描述
思路解析动画文字版
暴力做法是每来一个词,都和已有组逐个比较。比较前还要排序,组一多就慢。
把每个词排序后当 key。key 一样,直接塞进同一个桶,哈希表自动帮我们聚合。
先把 eat 拆成字符:异位词不是直接比较原串,而是先把字符拆开,准备归一化。
排序归一化 · eat → aet:排序后得到 key=aet。这个 key 才是进桶的身份证。
aet 还不存在 · 新建桶:哈希表里还没有 aet,就新建一个桶,把 eat 放进去。
tea 也排序成 aet:tea 的字母顺序不同,但排序后仍然是 aet,所以它应该回到同一个桶。
命中 aet · 加入同桶:key 命中已有桶,tea 不和 eat 逐字符比较,直接加入 aet 组。
轮到 tan · 排序成 ant:tan 排序后是 ant,和 aet 不一样。新 key,得开新桶。
ant 还不存在 · 再建一个桶:哈希表里没有 ant,新建第二个桶,把 tan 放进去。
ate 也排序成 aet:ate 字母顺序又不同,排序后还是 aet,应该回到第一个桶。
ate 命中 aet · 回到首桶:ate 排序后还是 aet,命中第一个桶。每个词都先排序再归桶,没有凭空分组。
key 设计对了,分组逻辑就只剩下塞桶。
边界三连:空字符串、单字符串和长度不同的词,都由同一个 key 规则自然处理。
雷区实演 · 原串当 key 会错:如果直接用原字符串,eat 和 tea 会落到两个桶,分组立刻错。
面试追问 1:异位词含相同字符,多重集合相同;排序后必然得到同一个字符串。
面试追问 2:可以,用 26 位计数元组当 key,避免每个词排序。
面试追问 3:LeetCode 通常不要求。只要每组内容正确即可。
这题学完不要乱跳,下一步去 对应专题 连刷同类题;卡住时用 AI 答疑追问“为什么这一步成立”,比只背答案更稳。
参考代码
from collections import defaultdictclass Solution: def groupAnagrams(self, strs): groups = defaultdict(list) for s in strs: key = ''.join(sorted(s)) groups[key].append(s) return list(groups.values())复杂度
- 时间复杂度:O(n·klogk),n 个词,每个词排序 klogk
- 空间复杂度:O(n·k),哈希表存下所有字符串
可套用的代码模板
记三步:把同类元素映射成同一个 key、用一行自动建桶、最后收集所有桶。换题只换‘归一化’那一行——比如字母异位词用排序串。
# 哈希分组三件套:归一化 key → 取桶 → 塞元素groups = defaultdict(list)for x in 输入: key = 归一化(x) # 排序串 / 26位计数元组 / 数值本身 groups[key].append(x) # 桶不存在 defaultdict 自动建return list(groups.values())易错点
面试追问把动画讲成自己的话
追问为什么排序串能当 key?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
前 K 个高频元素
LeetCode 347 · 中等 · 沿着 数组 & 哈希 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题