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

哈希表理论基础 

文章讲解:代码随想录

总结:

哈希表用于快速判断一个元素是否出现在集合里面。

如果不同数值的哈希值相等,就产生了哈希碰撞。解决方法包括  拉链法/链地址法(使用链表链接冲突元素)和开放地址法(换个位置,常见用线性探测法、平方探测法、双散列探测法、再散列)。

常见的三种哈希结构:数组、set(集合)、map(映射)。

因为红黑树是一种平衡二叉搜索树,key值是有序排列的,所以不能随意修改key的值,只能增加或删除。

使用集合,优先使用unordered_set,查询和增删效率最优;若集合有序,使用set;有序并且允许重复则使用multiset。

对于map,其中key是特定存储起来的,对于value的值并没有限制。

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

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

242.有效的字母异位词 

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

这道题本身很简单,不需要太多说明,值得注意的是,这道题可以用数组来做,主要是因为限制了数组的大小。

此外,这道题主要复习了:

  1. string的长度函数-s.length()。
  2. ASCII码,a-65,A-97。

349. 两个数组的交集 

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

建议:本题就开始考虑 什么时候用set 什么时候用数组,本题其实是使用set的好题,但是后来力扣改了题目描述和 测试用例,添加了 0 <= nums1[i], nums2[i] <= 1000 条件,所以使用数组也可以了,不过建议大家忽略这个条件。 尝试去使用set。

这道题主要使用unordered_set来实现,原因是题目需要去重而且对顺序没有要求,因为之前并没有接触过set这个数据类型,所以这道题很适合我这种新手来了解入门。

vector intersection(vector& nums1, vector& nums2) {
        unordered_set result_set;
        unordered_set nums1_set(nums1.begin(),nums1.end());
        for(int num:nums2){
            if(nums1_set.find(num)!=nums1_set.end()){
                result_set.insert(num);
            }
        }
        return vector(result_set.begin(),result_set.end());
    }

202. 快乐数 

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

建议:这道题目也是set的应用,其实和上一题差不多,就是 套在快乐数一个壳子。 

这里我和文章里面的做法基本一致,一开始解决这道题的这时候还是很懵的,但是后来注意到题目中提到无限循环就能证明它不是快乐数,循环就证明一组数重复出现,这里只要判断算出来的sum之前出现过即可,于是同样用到unordered_set来解决。

整体思路是简洁的,但是还是要记录一下求sum的过程。

bool isHappy(int n) {
        int sum=0;
        int num=n;
        unordered_set sum_set;
        while(true){
            sum=0;
            while(num){
                int yu=num%10;
                sum+=yu*yu;
                //num-=yu;
                num/=10;
            }            
            if(sum==1){
                return true;
            }else if(sum_set.find(sum)!=sum_set.end()){
                return false;
            }else{
                sum_set.insert(sum);
            } 
            num=sum;
        }
    }

1. 两数之和 

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

建议:本题虽然是 力扣第一题,但是还是挺难的,也是 代码随想录中 数组,set之后,使用map解决哈希问题的第一题。 

这道题很是巧妙,提示说会用到map,但我死活想不到怎么用的map,后来看了视频才知道,这里的map是按照<数值,下标>(<键,值>)来存储的,这样只需遍历一遍数组,遍历的过程中,查找(target-nums[i])这个键是否已经存在,就能找到对应的两个下标。

还要考虑的是,在知道了使用map的情况下,需要选择unordered_map来实现,主要考虑到题目对下标的有序性无要求,而且只需要找到一对下标即可,不涉及到需要存储两个键相同的值。

文章给出的做法中使用到了auto这个占位符(并不是变量类型,可以自动根据赋的值推导出变量的类型,这里iter的类型不是键的类型,还附带了值),主要是针对找不到键的情况,这里再次提醒了map只存储键,并不存储值。

vector twoSum(vector& nums, int target) {
        std::unordered_map map;
        for(int i=0;isecond,i};
            map.insert(pair(nums[i],i));
        }
        return {};
    }

总结

能看出来,今天的题目都是关于哈希表比较基础的题目,做完这些题目,能够加强对哈希表的基础知识的了解。

你可能感兴趣的:(代码随想录训练营,算法,哈希算法)