代码随想录算法训练营第五天| 242.有效的字母异位词、349. 两个数组的交集、 202. 快乐数、1. 两数之和

做提前需要直到哈希表理论基础,了解哈希表的内部实现原理,哈希函数,哈希碰撞,以及常见哈希表的区别,数组,set 和map,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。 

文章讲解:代码随想录

242.有效的字母异位词

题目链接/文章讲解/视频讲解: 代码随想录

 1.代码展示:

 bool isAnagram(string s, string t) {
        //考虑到字母a-z为连续的26个字母,因此使用数组就可以
        //step1 构造数组
        //注意:一定要初始化数组!!!
        //否则数组中的值会乱套
        int hash[26] = {0};
        //step2 统计s中每个字符的个数并记录
        for (int i = 0; i < s.size(); i++) {
            hash[s[i] - 'a']++;
        }
        //step3 统计t中每个字符的个数并记录
        for (int j = 0; j < t.size(); j++) {
            hash[t[j] - 'a']--;
        }
        //step4 统计hash表内每个字符个数
        //数组没有size()函数
        for (int k = 0; k < 26; k++) {
            if (hash[k] != 0) {
                return false;
            }
        }
        return true;
    }

 2.本题小节

        本题之所以选用数组,是因为字母只有26个,需要寻找的范围很小,数组的不同索引对应着不同字母出现的次数,只要直到这点,这题就很好做了。

349. 两个数组的交集

题目链接/文章讲解/视频讲解: 代码随想录

 1.代码展现

//349 两个数组的交集
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        //方法一 用set来做
        //step1 构建储存结果的容器以及处理数据的容器
        //注意:包含头文件
        unordered_set<int> usResult;
        unordered_set<int> usNums(nums1.begin(), nums1.end());
        //step2 遍历数组2,通过hash方式查找数组2中的数据
        for (int i = 0; i < nums2.size(); i++) {
            //查询到
            if (usNums.count(nums2[i])) {
                //step3 查询到,储存起来
                //注意:这里的容器有去重的作用
                usResult.insert(nums2[i]);
            }
        }
        return vector<int> (usResult.begin(), usResult.end());

        //方法二 用vector来做
        unordered_set<int> snResult;
        int nNums[1001] = {0};
        for (int i = 0; i < nums1.size(); i++) {
            //做标记,同时也可以防止重复
            nNums[nums1[i]] = 1;
        }
        for (int i = 0; i < nums2.size(); i++) {
            if (nNums[nums2[i]] == 1) {
                snResult.insert(nums2[i]);
            }
        }
        return vector<int>(snResult.begin(), snResult.end());
    }

2.本题小节

        本题既可以用set也可以用数组。首先要注意的是使用 unordered_set的话需要包含头文件“unordered_set”, unordered_set中的值不能重复,因此使用找个容器有去重的作用。本题由于修改了输入的数组长度小于1000,并且数也小于1000,因此也可以使用数组,但是可以看出来,相较于set,数组占用了更多的空间,下标与要寻找的数是可以相同的,因此可以用数组来寻找。

202. 快乐数

题目链接/文章讲解:代码随想录

 1.代码展现

 //202 快乐数
    //求解各个位平方和
    int doSqurSum(int n) {
        int nSum = 0;
        //直到n所有位置都计算过
        while (n) {
            //step1 计算n中最后一位平方和
            nSum += (n % 10) * (n % 10);
            //step2 去掉n中最后一位
            n /= 10;
        }
        return nSum;
    }
    
    bool isHappy(int n) {
        unordered_set<int> nNum_set;
        int nSum;
        while (1) {
            //step1 计算各个位数平方和
            nSum = doSqurSum(n);
            //step2 判断sum是否为1
            if (nSum == 1) {
                return true;
            }
            //step3 如果sum出现过,那么久证明
            //该数不为快乐数
            if (nNum_set.count(nSum)) {
                return false;
            }
            else {
                nNum_set.insert(nSum);
            }
            //step4 重新给n赋值
            n = nSum;
        }
    }

 2.本题小节
        首先要知道各个数的平方和如何计算,如上述代码,从各位开始算,然后是如何处理计算后的数,有三种情况,如果1,那么就满足快乐数,返回为真;如果出现过,那么不可能为快乐数,返回假,如果以上情况都不满足,那么给n赋值继续算,直到满足上面的一种情况。
        这里要注意的就是出现过这种情况用到了哈希表,由于不知道找个数是多大,也不知道需要计算多少次(表的长度),因此就使用unordered_set来储存计算后的结果。

1. 两数之和

 题目链接/文章讲解/视频讲解:代码随想录

 1.代码展示

    //1 两数之和
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map <int ,int> mnNums;
        for (int i = 0; i < nums.size(); i++) {
            int nTemp = target - nums[i];
            if (mnNums.count(nTemp)) {
                return {mnNums.find(nTemp)->second, i};
            }
            mnNums.insert(make_pair(nums[i], i));
        }
        return {};
    }

 2.本题小节

        如果要使用哈希表方法的话,就不要被两数之和迷惑,因为这里的和是固定的,因此已知和和另外一个数,那么就可以求要寻找的数。如果找找个数呢,这个时候就要用到哈希表了,由于要返回的是被寻找到数的下表,因此这里用unordered_map,储存数和对应的下表,这里的储存时机很巧妙,可以看出,遍历时第一次寻找值的时候根本不可能找到,因为map中啥也没有,在未找到之后储存当前数及其对应下标,从第二次开始就可以寻找之前的数。

        我自己最开始做的是先把数组都储存到map中,然后再寻找数,但是这样会碰到寻找到本身或者是漏掉的情况(当数组中有两个相同的值时),但是使用上述的方式,就不会出现这两种情况。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值