赞
踩
核心问题在于如何(快速)判断字母异位词,很容易想到字符串匹配里面的RK算法
,其实就是一种编码方式。最简单的可以将每个单词的每个字母的ascii码
加起来,因为字母异位词加起来得到的和必然是相同的,但是单词太多就可能冲突:不是字母异位词加起来也可能相同,既然加不行,可以乘啊,而且不一定非要用一个整数来编码,用字符串也可以,排序就是字符串的思路。
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
vector<vector<string>> res;
unordered_map<string, vector<string>> m;
for(int i = 0; i < strs.size(); ++i){//排序
auto s = strs[i];
sort(s.begin(), s.end());
m[s].push_back(strs[i]);
}
for(const auto &v : m) res.push_back(v.second);
return res;
}
};
优化一下:
class Solution { public: vector<vector<string>> groupAnagrams(vector<string>& strs) { vector<string> res[strs.size()]; unordered_map<string, int> m;//int对应的是res中的下标 int cnt = 0; for(const auto &s : strs){//排序 auto tmp = s; sort(tmp.begin(), tmp.end()); if(!m.count(tmp)){ res[cnt].push_back(s); m[tmp] = cnt++; } else res[m[tmp]].push_back(s); } return {res, res + cnt}; } };
编码成一个数字的难点是需要考虑冲突问题,类似哈希冲突,而且字符串长的话,需要考虑溢出问题。借用题目评论里提到的质数思路:
class Solution { public: int m[26] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101}; vector<vector<string>> groupAnagrams(vector<string>& strs) { vector<string> res[strs.size()]; unordered_map<int, int> map;//<编码值,res下标> int cnt = 0, mod = 1e9+7; for(const auto &s : strs){//排序 long v = 1; for(const auto &c : s){ v *= m[c-'a']; v %= mod;//取模防止溢出 } if(!map.count(v)){ res[cnt].push_back(s); map[v] = cnt++; }else res[map[v]].push_back(s); } return {res, res + cnt}; } };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。