LeetCode第 49 题:字母异位词分组(C++)

49. 字母异位词分组 - 力扣(LeetCode)
在这里插入图片描述

核心问题在于如何(快速)判断字母异位词,很容易想到字符串匹配里面的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};
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值