每日一题2023.7.16|49.字母异位词

49.字母异位词

链接: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;
    }
};

在解题过程中发现,质数设置的不合理还是会报错。此时更换几个质数即可。

你可能感兴趣的:(数据结构与算法之美,哈希算法,算法,leetcode,c++)