力扣49题-字母异位词分组C++ && 哈希表 个人理解

0.哈希表想法的延续

学习代码随想录的时候看到了【字母异位词】这个概念。代码随想录 (programmercarl.com)

简单说一下针对【字母异位词】从定义出发的代码表示。统计一个单词每个字母的出现次数,最多只有26个字母,所以使用26个「坑」来记录每个字母的出现次数,如果两个单词的每个字母出现次数都一致,那么这两个单词就是【字母异位词】。

针对代码随想录给出的这道例题,采用了一种很巧妙的方式来【比较】,因为是两个单词比较,所以第一遍统计采用【加法】,第二遍统计采用【减法】,如果两个单词是【字母异位词】,那么会在每一个字母上【加减相抵】最后就是全0

对于第49题,就需要用一点小巧思。

1.哈希在何处

哈希需要有key和value,根据第0部分给出的【字母异位词】定义的表示,我们可以发现,如果一些单词是字母异位词,那么它们的字母计数「坑」长得应该一模一样。而用什么样的表示可以体现出一模一样呢?

如果和代码随想录例题一样,采取数组的方式,作为key显然是不合适的。就算不考虑key这一层,要比较两个数组是否一致,就需要遍历一遍数组,如果有n个待判断的字符串,那时间复杂度就达到了O(n^2)——欢迎指正,如果这里的时间复杂度分析错了的话。

这时候,有一个神奇的数据结构——【字符串】出现了。它可以使用类似数组的方式访问,同时字符串的相等很好判断,此外字符串作为key并没有什么让人觉得奇怪的地方。所以我们使用【字符串】来统计每个单词的字符出现次数。

那接下来就是value是什么了。这里就比较水到渠成了,刚刚有cue到——”如果一些单词是字母异位词,那么它们的字母计数「坑」长得应该一模一样“。从哈希的角度来说,就是经过我的【统计函数】,【字母异位词】会被映射到同一个key(位置)下。而这就是我们想要的。于是,使用vector来存储【字母异位词】列表(就很像解决哈希冲突的拉链法哈哈哈)。

2.中间数据结构的设计

单独拎出来表示一下上一部分说的哈希表的表示。key是统计字母的字符串,value是单词列表。用C++声明就是:

unordered_map<string,vector<string>>

3.代码实现

class Solution {
public:
    
    string countLetter(const string& s){
        string count(26,'0');//生成一个26位全0字符串
        for(auto c:s){
            count[c-'a']++;
        }
        return count;//返回统计每个字母出现次数的字符串,作为key
    }
    vector<vector<string>> groupAnagrams(vector<string>& strs){
        //对每一个单词建立一个字母统计数组,统计结果一样的分一组——统计结果作为key
        unordered_map<string,vector<string>> res;//key为字母统计结果,value为相同字母统计结果的string列表
        for(string str:strs){
            string count=countLetter(str);
            res[count].push_back(str);//当前str入相同计数的队列
        }
        // 转换格式
        vector<vector<string>> finalRes;
        for(auto it=res.begin();it!=res.end();it++){
            finalRes.push_back(it->second);
        }
        return finalRes;
    }
};

4.写在最后

在周末被这道题卡住之后,主打一个一蹶不振。今天在GPT大人的帮助下,终于理解了这个解法的idea了。官方题解的【排序】也是我完全没想到的切入点。

哎,道阻且长。

最后一个小tips送给自己:

在函数string countLetter(const string& s)中,参数要声明为const类型,因为传入的是引用,而我们只要获得它的值就可以了,为了防止修改引用的变量值,需要声明为const类型。

哈希真是好东西,明天继续冲算法!!加油!!!!

Energy and persistent conquer all things.

一定拿下,全都拿下。㊗️大家金三银四顺利。

于 二月二,龙抬头。

  • 38
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值