前言
记录一下刷题历程 力扣第49题字母异位词分组 用哈希表
字母异位词分组
原题目:
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
示例 1:
输入: strs = [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
输出: [[“bat”],[“nat”,“tan”],[“ate”,“eat”,“tea”]]
示例 2:
输入: strs = [“”]
输出: [[“”]]
示例 3:
输入: strs = [“a”]
输出: [[“a”]]
分析
我们可以通过一个哈希表 把单词排序后的字符串数组进行分组比如”eat,tea,ate“都放入”aet"这一类中,但是因为我们还需要对单词进行排序才能作为哈希表的键,有没有更方便的方法呢?我们可以记录单词里字母出现的频率。
代码如下:
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
// 结果数组,用于存放分组后的异位词
vector<vector<string>> res;
// 哈希表,键为字符频次统计字符串,值为对应的异位词数组
unordered_map<string, vector<string>> u_mapRes;
// 遍历给定的字符串数组
for(auto& str : strs) {
// 统计当前字符串中每个字符出现的频次,用一个长度为26的字符串表示
string count(26, '0');
for(auto& c : str) {
count[c - 'a'] += 1; // 统计每个字符的频次
}
// 将统计字符串作为键,当前字符串作为值,存入哈希表
u_mapRes[count].push_back(str);
}
// 将哈希表中的值(即各组异位词数组)加入结果数组中
for(auto& pair : u_mapRes) {
res.push_back(pair.second);
}
// 返回最终的分组结果数组
return res;
}
};
解释注释
1.vector<vector> res;
初始化一个二维向量 res,用于存放最终的分组结果,每个元素是一个字符串数组,表示同一组的异位词。
2.unordered_map<string, vector> u_mapRes;
使用哈希表 u_mapRes,键为字符频次统计字符串,值为对应的异位词数组。这里的 string 是由每个字符的频次组成的字符串,用来作为异位词的唯一标识。
3.第一个循环 (for(auto& str : strs)):遍历字符串数组
string count(26, ‘0’);
初始化一个长度为 26 的字符串 count,用 ‘0’ 初始化,表示每个字符的初始频次为 0。
for(auto& c : str) { count[c - ‘a’] += 1; }
遍历当前字符串 str 中的每个字符 c。c - ‘a’:这一部分计算当前字符 c 相对于字母 ‘a’ 的偏移量(即字母在字母表中的位置)。例如,如果 c 是 ‘a’,那么 c - ‘a’ 结果是 0;如果 c 是 ‘b’,结果是 1;以此类推。将字符在 count 中对应的位置加 1,表示统计每个字符的出现次数。
u_mapRes[count].push_back(str);
将统计字符串 count 作为键,当前字符串 str 作为值,将当前字符串加入到对应的异位词数组中。
4.第二个循环 (for(auto& pair : u_mapRes)):遍历哈希表
res.push_back(pair.second);
将哈希表中每个键值对的值(即异位词数组)加入到结果数组 res 中,完成分组。
时间复杂度
这个方法的时间复杂度主要取决于遍历字符串数组和统计字符频次的操作,是 O(n * m),其中 n 是字符串数组 strs 的长度,m 是字符串的平均长度。因为在遍历字符串和计算频次时,都是线性操作。