主题
题意解读
如果两个字符串从小到大排序后相等,那么两个字符串就互为字母异位词,否则不是。
例如
示例 1 是怎么算的?
输入
每个字符串各自排序,得到
把排序后相同的字符串分到同一组:
- 排序后是
的字符串,排序前是 。 - 排序后是
的字符串,排序前是 。 - 排序后是
的字符串,排序前是 。
因此,示例 1 返回的二维列表中,包含三个列表,分别为
。 。 。
三个列表的顺序随意。
算法
用哈希表分组,把排序后的字符串当作哈希表的 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;
}
};复杂度分析
- 时间复杂度:
,其中 为 的长度, 为 的长度。每个字符串排序需要 的时间,有 个字符串,所以总的时间复杂度为 。 - 空间复杂度:
。
分类题单
- 滑动窗口与双指针(定长/不定长/单序列/双序列/三指针/分组循环)
- 二分算法(二分答案/最小化最大值/最大化最小值/第K小)
- 单调栈(基础/矩形面积/贡献法/最小字典序)
- 网格图(DFS/BFS/综合应用)
- 位运算(基础/性质/拆位/试填/恒等式/思维)
- 图论算法(DFS/BFS/拓扑排序/基环树/最短路/最小生成树/网络流)
- 动态规划(入门/背包/划分/状态机/区间/状压/数位/数据结构优化/树形/博弈/概率期望)
- 常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树)
- 数学算法(数论/组合/概率期望/博弈/计算几何/随机算法)
- 贪心与思维(基本贪心策略/反悔/区间/字典序/数学/思维/脑筋急转弯/构造)
- 链表、树与回溯(前后指针/快慢指针/DFS/BFS/直径/LCA)
- 字符串(KMP/Z函数/Manacher/字符串哈希/AC自动机/后缀数组/子序列自动机)
欢迎关注 B站@灵茶山艾府