音乐
暂未播放
LeetCode | 字母异位词分组
分类:哈希表 / 字符串 / 排序 / 计数
题目#
给定一个字符串数组 strs,把所有字母异位词分到同一组。
字母异位词指的是:两个字符串包含的字母完全相同,只是顺序不同。
示例:
1输入:strs = ["eat", "tea", "tan", "ate", "nat", "bat"]2输出:[["bat"], ["nat", "tan"], ["ate", "eat", "tea"]]返回结果中,每一组内部的顺序、组和组之间的顺序都不重要。
讲解#
这道题的关键是:同一组字母异位词需要有同一个标识。
排序法#
把字符串里的字符sort排序后,字母异位词会得到同一个结果。所以可以把排序后的字符串作为哈希表的 key。
具体做法:
- 准备一个字典
mp。 - 遍历每个字符串
st。 - 对
st里的字符排序,得到key。 - 把原字符串
st放进mp[key]对应的列表里。
计数法#
字母异位词不一定要排序才能判断,也可以数每个字母出现了几次。
所以可以用一个长度为 26 的数组记录每个小写字母出现次数。这个数组转成元组后,也可以作为哈希表的 key。
计数法避免了排序,所以每个字符串只需要扫描一遍。
复杂度#
这里 n 是字符串数量,k 是单个字符串的最大长度。
- 排序法:
- 时间复杂度:
O(n * k * log(k)) - 空间复杂度:
O(n * k)
- 时间复杂度:
- 计数法:
- 时间复杂度:
O(n * k) - 空间复杂度:
O(n * k)
- 时间复杂度:
排序法里的 log(k) 来自排序。对一个长度为 k 的字符串排序,常见排序算法的时间复杂度是 O(k * log(k))。
可以用“归并排序”来理解这个复杂度。假设有 k 个字符要排序:
1第 1 层:把 k 个字符分成 2 组2第 2 层:继续分成 4 组3第 3 层:继续分成 8 组4...每往下一层,问题规模大约减半,所以总层数大约是 log(k)。
分完以后还要一层一层合并。每一层合并时,所有字符加起来都会被处理一遍,也就是 k 次左右。
所以可以理解成:
1每一层处理 k 个字符2一共有 log(k) 层3总时间复杂度 = O(k * log(k))Python 的 sorted 底层不是简单的归并排序,而是 Timsort。不过从这道题分析复杂度时,可以按常见排序的 O(k * log(k)) 来理解。
计数法不排序,只扫描每个字符串里的字符。扫描一个长度为 k 的字符串是 O(k),扫描 n 个字符串就是 O(n * k)。
一些语法基础#
sorted(st) 会把字符串 st 里的字符拿出来排序,返回的是列表,不是字符串。sorted(“eat”)结果是:[“a”, “e”, “t”]
join 是字符串的方法,格式是:连接符.join(字符串列表),例如”-“.join([“a”, “e”, “t”])结果是:“a-e-t”
计数法里会用到 ord(ch) - ord("a")。ord(ch) 会得到字符对应的数字编号,所以减去 ord("a") 之后,就能把小写字母转成 0 到 25 的下标:
tuple(counts) 是把列表转成元组。字典的 key 必须是不可变的,列表可以修改,所以不能当 key;元组不能修改,所以可以当 key。计数法里要把 counts 转成 tuple 再放进字典。
代码#
排序法#
源码#
1from collections import defaultdict2from typing import List3
4
5class Solution:6 def groupAnagrams(self, strs: List[str]) -> List[List[str]]:7 mp = defaultdict(list)8
9 for st in strs:10 key = "".join(sorted(st))11 mp[key].append(st)12
13 return list(mp.values())计数法#
源码#
1from collections import defaultdict2from typing import List3
4
5class Solution:6 def groupAnagrams(self, strs: List[str]) -> List[List[str]]:7 mp = defaultdict(list)8
9 for st in strs:10 counts = [0] * 2611 for ch in st:12 counts[ord(ch) - ord("a")] += 113 mp[tuple(counts)].append(st)14
15 return list(mp.values())测试#
1def normalize(groups):2 return sorted(sorted(group) for group in groups)3
4
5sol = Solution()6
7ans = sol.groupAnagrams(["eat", "tea", "tan", "ate", "nat", "bat"])8assert normalize(ans) == normalize([["bat"], ["nat", "tan"], ["ate", "eat", "tea"]])9
10assert normalize(sol.groupAnagrams([""])) == normalize([[""]])11assert normalize(sol.groupAnagrams(["a"])) == normalize([["a"]])12
13print("PASS")参考资料#
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
部分内容可能已过时
评论区
分享你的想法,与大家交流讨论
音乐
暂未播放



