链接:LeetCode49.字母异位词
官方题解
由于互为字母异位词的两个字符串包含的字母相同,因此对两个字符串分别进行排序之后得到的字符串一定相同,故可以将排序之后的字符串作为哈希表的键;
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
unordered_map<string,vector<string>> ma;
for(const string &str:strs){
string key = str;
sort(key.begin(),key.end());
ma[key].push_back(str);
}
vector<vector<string>> ans;
for(auto it=ma.begin();it!=ma.end();++it){
ans.push_back(it->second);
}
return ans;
}
};
时间复杂度为O(nklogk)其中n是strs中字符串的数量,k是strs中字符串的最大长度。需要遍历n个字符串,对于每个字符串,需要O(klogk)的时间进行排序以及O(1)的时间更新哈希表;
空间复杂度为O(nk)
由于互为字母异位词的两个字符串包含相同的字母,因此两个字符串中相同字母出现的次数一定是相同的,故可以将每个字母出现的次数使用字符串表示作为哈希表的键;
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
unordered_map<string,vector<string>> ma;
for(const string &str:strs){
string s(26,'0');
for(const char&c:str) s[c-'a']+='1';
ma[s].push_back(str);
}
vector<vector<string>> ans;
for(auto it=ma.begin();it!=ma.end();++it){
ans.push_back(it->second);
}
return ans;
}
};
第一次拿到这道题的解题思路是:
将strs中的每个字符串的每个字符的数值之和作为哈希表的键,提交代码发现之后运行错误。然后根据错误案例分析出现地方为:两个不是字母异位词的字母所得到的数值和可能相等。于是想了第二个办法:将strs中每个字符串中字符出现的次数映射在哈希表中。但是时间超出限制。
错误代码
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
vector<vector<string>> ans;
vector<string> res;
unordered_map<int,bool> ma;
unordered_map<int,unordered_map<char,int>>mh;
for(int i=0;i<strs.size();++i){
for(int j=0;j<strs[i].size();++j) ++mh[i][strs[i][j]];
}
for(int i=0;i<strs.size();++i) ma[i]=false;//刚开始都没有用过
for(int i=0;i<strs.size();++i){
if(ma[i]) continue;
ma[i] =true;
res.push_back(strs[i]);
string s1 = strs[i];
for(int j=i+1;j<strs.size();++j){
if(ma[j]) continue;
bool flag=true;
string s2 = strs[j];
if(s1.size()!=s2.size()) flag=false;
else{
for(int k=0;k<s2.size();++k){
if(mh[i][s2[k]] != mh[j][s2[k]]) {flag=false;break;}
}
}
if(flag) {res.push_back(strs[j]);ma[j] =true;}
}
ans.push_back(res);
res.clear();
}
return ans;
}
};
时间复杂度为O(n^2 * k)其中n为strs字符串数量,k为字符串最大长度
空间复杂度为O(n*k)
根据质因数分解的原理,将每个字符抽象成一个质数,然后每个字符串字符对应质数的乘积作为哈希表的键;
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
//不能从1开始因为1乘以b等于b
int zhishu[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,101,103};
unordered_map<uint64_t,vector<string>>ma;
for(const string&str:strs){
uint64_t te=1;
for(const char&c:str) {te = ((te%INT_MAX)*zhishu[c-'a'])%INT_MAX;}
//cout<
ma[te].push_back(str);
}
vector<vector<string>> ans;
for(auto it=ma.begin();it!=ma.end();++it){
ans.push_back(it->second);
}
return ans;
}
};
在解题过程中发现,质数设置的不合理还是会报错。此时更换几个质数即可。