🧩 LeetCode 49 - Group Anagrams 字母异位词分组
这道题是 LeetCode 字符串 + 哈希表的经典面试题,也非常适合学习 STL 容器和模板编程的实战应用。
✅ 题目简介
给定一个字符串数组 strs
,请你将字母异位词组合在一起。可以按任意顺序返回结果。
字母异位词是由相同字母构成,但顺序不同的字符串。
🎯 示例:
输入:["eat", "tea", "tan", "ate", "nat", "bat"]
输出:[["eat","tea","ate"],["tan","nat"],["bat"]]
🧠 解题思路
1. 什么是字母异位词?
字母异位词(Anagram)满足:
- 字符种类相同 ✅
- 各字符数量相同 ✅
- 顺序不同也没关系 ✅
举例:
"eat"
→"aet"
"tea"
→"aet"
"tan"
→"ant"
我们发现,只要将字符串排序后相同,它们就是一组异位词!
2. 核心思想(排序 + 哈希)
- 遍历每个字符串,对它排序后作为 key
- 用
unordered_map<string, vector<string>>
把所有原始字符串s
放入对应组 - 遍历 map,把所有 value(vector
)提取出来组成最终结果
✅ 完整 C++ 代码实现
#include <vector>
#include <string>
#include <unordered_map>
#include <algorithm>
using namespace std;
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
unordered_map<string, vector<string>> hash;
for (string s : strs) {
string key = s;
sort(key.begin(), key.end()); // 排序后的字符串作为 key
hash[key].push_back(s); // 把原始字符串分到对应组
}
vector<vector<string>> result;
for (auto& pair : hash) {
result.push_back(pair.second); // 提取每组异位词
}
return result;
}
};
🧪 示例详解
输入:["eat", "tea", "tan", "ate", "nat", "bat"]
排序过程变成:
原字符串 | 排序后 key | 分组情况 |
---|---|---|
eat | aet | [“eat”] |
tea | aet | [“eat”, “tea”] |
tan | ant | [“tan”] |
ate | aet | [“eat”, “tea”, “ate”] |
nat | ant | [“tan”, “nat”] |
bat | abt | [“bat”] |
最终结果为:
[["eat", "tea", "ate"], ["tan", "nat"], ["bat"]]
🧰 语法讲解小合集
✅ sort 是什么?
sort(key.begin(), key.end());
- C++ 中的标准排序函数,来自
<algorithm>
- 默认按升序排列
- 用于将字符串转为统一形态,例如
"tea"
→"aet"
✅ hash[key].push_back(s) 放哪?
这句放在 for 循环内部,每次处理一个字符串后:
string key = s;
sort(key.begin(), key.end());
hash[key].push_back(s); // 🌟 按排序后的 key 分组
✅ auto& pair 是什么语法?
for (auto& pair : hash)
auto&
:自动推导引用类型,节省写unordered_map<string, vector<string>>::iterator
的麻烦pair.first
是 key(排序后的字符串)pair.second
是 value(一组异位词)
✅ 是模板编程吗?
严格来说:
- 你没写
template<typename T>
(没有写模板函数) - 但用了 STL 提供的模板类(比如
vector<string>
是vector<T>
模板的实例) - 所以你这段属于:模板编程的应用层 ✔️
📊 时间与空间复杂度分析
-
时间复杂度:O(n * m log m)
- n = 字符串数量
- m = 字符串最大长度(排序)
-
空间复杂度:O(n * m)
- 哈希表存所有字符串分组
🔁 拓展思考:不用排序可以吗?
当然可以,方式是:
- 用长度为 26 的 int 数组记录每个字符串的字母频率
- 通过哈希把频率数组编码为 key
- 可以跳过排序,提升效率,适合数据量大或字符集已知的场景
✏️ 小结
- 本题考察排序+哈希分组技巧,关键在于理解“异位词的标准形式”
- STL 容器(vector/map)、模板类和
auto
使用贯穿全题 - 是一道极佳的面试准备题,能覆盖多个 C++ 语言点!