

零、题目描述
题目链接:力扣 49. 字母异位词分组
题目描述:

示例 1:
输入: strs = [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
输出: [[“bat”],[“nat”,“tan”],[“ate”,“eat”,“tea”]]
解释:
在 strs 中没有字符串可以通过重新排列来形成 “bat”。
字符串 “nat” 和 “tan” 是字母异位词,因为它们可以重新排列以形成彼此。
字符串 “ate” ,“eat” 和 “tea” 是字母异位词,因为它们可以重新排列以形成彼此。
示例 2:
输入: strs = [“”]
输出: [[“”]]
示例 3:
输入: strs = [“a”]
输出: [[“a”]]
提示:
1 <= strs.length <= 104
0 <= strs[i].length <= 100
strs[i] 仅包含小写字母
一、为什么这道题值得你花几分钟的时间看完?
这道题是哈希表应用的经典入门题,更是面试中“考察基础数据结构运用能力”的高频题——它完美融合了“泛式编程的容器活用”与“算法思维的核心逻辑”,不仅考察我们对哈希映射的理解还考察对泛式编程中容器掌握的熟练度。
题目核心价值
- 容器能力的“试金石”:集中考察
unordered_map的键值映射、vector的嵌套存储等核心用法,容器用得熟则解题如“简单题”,反之则会将中等题变成困难题,是检验泛式编程基础的绝佳案例。 - 直击哈希表核心思想:精准考察“键值设计”思维——如何将“字母异位词”这一抽象关系,转化为哈希表可识别的唯一键,是解题的核心,而非单纯的语法调用。
- 多知识点协同融合:串联“排序算法”与“哈希表存储”,考察对不同数据结构的搭配运用能力,而非单一知识点的机械记忆。
- 实际场景的“缩影”:类似“分组归类”问题(如日志分类、数据去重、特征聚合)在工作中高频出现,解题思路可直接迁移复用。
- 面试的“区分利器”:能快速筛选出“只会死记语法”和“理解底层逻辑”的候选人——基础选手能靠容器用法写出常规解法,进阶选手能拓展优化方案、分析优劣,契合面试选拔标准。
面试考察的核心方向
- 容器选型的底层逻辑:为何用
unordered_map而非map,vector嵌套存储的合理性,能否说清容器特性与题目场景的匹配度。 - 键值设计的创新思维:能否快速想到“统一标识”核心思路,除排序外是否能拓展计数统计等方案,及其优劣对比。
- 语法与逻辑的协同:是否能将容器用法与“哈希分组”逻辑结合,避免“懂语法却想不出思路”或“有思路却写不对代码”。
- 复杂度分析的准确性:能否清晰说明排序+哈希组合的时间/空间代价,理解容器操作对复杂度的影响。
- 边界场景的兼容能力:对空字符串、单字符字符串、重复字符串等特殊用例的处理,体现代码的稳健性。
掌握这道题,既能夯实泛式编程的容器使用基础,又能加深理解“哈希表分组”的核心逻辑,后续遇到类似“归类统计”问题都能举一反三,无论笔试还是面试都能从容应对。
二、题目解析
字母异位词的核心定义是:字母种类和数量完全相同,仅排列顺序不同的字符串。
题目本质是“归类问题”——将满足“异位词关系”的字符串划分到同一组,不满足的单独成组,最终返回所有组的集合。
解题的关键突破口的是:找到异位词的“统一标识”,让同一组异位词对应同一个标识,不同组对应不同标识,再通过哈希表以“标识为键、字符串列表为值”的形式,实现自动分组
三 、算法原理
本题核心算法是 “排序+哈希表”,思路简洁且高效,步骤拆解如下:
1. 统一标识的设计
同题目解析中说的异位词的本质是“字母构成一致”,那么排序后会得到完全相同的字符串——这就是最直观的“统一标识”。
- 如:
“eat”“tea”“ate”排序后均为“aet”;“nat”“tan”排序后均为“ant”,“bat”排序后为“abt”。 - 以排序后的字符串作为哈希表的“键”,原字符串作为“值”存入对应键的列表中,自然就能将所有异位词归为一组。
以示例一为例:(最终哈希表中的映射)

2. 算法步骤
- 初始化哈希表:选用
unordered_map<string, vector<string>>,键为排序后的字符串,值为存储原字符串的向量; - 遍历字符串数组:对每个原字符串,先复制一份并排序,得到其“统一标识”;
- 存入哈希表:将原字符串插入到标识对应的向量中;
- 提取结果:遍历哈希表,将所有向量依次存入结果集,返回即可。
四、代码实现
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
// 哈希表:key=排序后的统一标识,value=对应异位词列表
unordered_map<string, vector<string>> hash;
for (auto e : strs) {
string key = e; // 复制原字符串作为key的基础
sort(key.begin(), key.end()); // 排序得到统一标识
hash[key].push_back(e); // 原字符串存入对应组
}
vector<vector<string>> ret;
// 遍历哈希表,收集所有组到结果集
for (auto& [key, group] : hash) {
ret.push_back(group);
}
return ret;
}
};
代码细节与易错点
- 避免修改原字符串:必须复制原字符串后再排序,直接排序原字符串会导致原始数据丢失无法正确进行键值对映射。
- 哈希表遍历方式:使用
auto& [key, group]的结构化绑定,高效遍历键值对,注意加引用避免拷贝。 - 空字符串处理:空字符串排序后仍为空字符串,哈希表会自动将其归为一组,无需额外处理。
- 容器选择理由:
unordered_map的查找和插入效率为O(1)(平均情况),优于map的O(log n),更适合本题场景。
复杂度分析
- 时间复杂度:O(n * k log k)。n为字符串数组长度,k为单个字符串的最大长度;遍历数组耗时O(n),每个字符串排序耗时O(k log k),整体由排序主导;
- 空间复杂度:O(n * k)。哈希表需存储所有字符串,总存储量为所有字符串的长度之和,最坏情况下为n * k。
五 、总结
核心考点回顾
- 哈希表的“键值设计思维”:将抽象的“异位词关系”转化为具体的“统一标识”,是解题核心。
- 数据结构协同运用:排序用于生成标识,哈希表用于分组存储,二者互补实现高效解题。
- 复杂度优化意识:了解排序法与计数法的优劣,能根据场景选择更优方案。
解题思路迁移
- 分组归类问题:只要能找到“统一标识”,均可采用“哈希表+标识生成”的思路(如日志按日期分组、文件按类型分组)。
六、下题预告
下一篇我们就开启字符串的学习之旅!字符串题型常常结合其他算法考察,内容丰富又有挑战性,我们会从 力扣 14. 最长公共前缀 这道模拟题开始,一道一道熟悉字符串的常用接口、解题思路和实用技巧,一步步攻克这类高频面试题!
Doro 带着小花🌸来啦!🌸奖励🌸坚持坚持看到这里的你!哈希表 “用空间换时间” 的核心逻辑超实用,能掌握它的使用场景和解题技巧,已经超厉害啦~
相信现在的你,对哈希表的解题思路已经心中有数,下次遇到需要快速查找、去重的题目,一定能第一时间想到用哈希表破局。把这篇内容收藏起来,后续刷题时遇到哈希表相关题型,随时翻查就能快速唤醒记忆。
如果你在今天的哈希表学习中有任何疑问 —— 比如哈希表的选型、键值对的设计,或者有更优的解题思路,都可以发到评论区,博主看到会第一时间回复。
最后别忘了点个赞关注博主呀,你的支持就是博主持续更新优质算法内容的最大动力,我们下道题不见不散!

433





