代码随想录--哈希表--两个数组的交集题型、快乐数题型、两数之和题型

两个数组的交集题型:

http://学透哈希表,set使用有技巧!Leetcode:349. 两个数组的交集

补充一点基础知识:

关于set,C++ 给提供了如下三种可用的数据结构:
std::set
std::multiset
std::unordered_set
std::set和std::multiset底层实现都是红黑树,std::unordered_set的底层实现是哈希表, 使用unordered_set 读写效率是最高的,并不需要对数据进行排序,而且还不要让数据重复,所以选择unordered_set。

unordered set这种数据结构有自动去重的操作,就是即使你往里面加100个元素2,它最终只保留一个元素2


①怎么创建哈希表?
比如创建一个哈希空表A :
unordered_set A; 
②怎么把nums1的值放进哈希表?
比如创建一个哈希表B,然后把数组nums1的值放进哈希表B中 :
unordered_setB (nums1.begin(), nums1.end());
③怎么查找某个值是否在哈希表中?
使用find,返回的是被查找元素的位置,没有则会返回map.end()。
所以if (nums_set.find(num) != nums_set.end()) {
                result_set.insert(num);
            }
④最后返回那步,怎么把哈希表set放进数组vector中的,为啥不直接返回set?
因为题目要求返回数组形式,那怎么把哈希表转换为数组 :
 vector(result_set.begin(), result_set.end());


大致代码套路
unordered_set result_set;
     unordered_set nums_set(nums1.begin(),nums1.end());
     for(int i=0;i           if(nums_set.find(nums2[i])!=nums_set.end()){
             result_set.insert(nums2[i]);
           }
    }
      return vector(result_set.begin(),result_set.end());

力扣之前是没有限制数值大小,所以不能用数组,现在又改了范围变成1000之内,所以这时候也可以用数组了。

设置一个1001的数组hash且均为0,然后循环nums1,把对应的hash[nums1]变成1,此时hash[]等于1的说明在nums1中存在,等于0则不存在。
然后再循环nums2,判断hash[nums2]是否等于1,等于1就说明是交集,我们用的是unordered_set result_set,所以已经自动去重,最终返回数组形式即可。
数组的大致代码套路
int hash[1001]={0};
     unordered_set result_set;
for(int i=0;i     hash[nums1[i]]=1;
   }
for(int i=0;i    if(hash[nums2[i]]==1){
             result_set.insert(nums2[i]);
         }
   }
return vector(result_set.begin(),result_set.end());

快乐数题型:

①思路,这道题目看上去貌似一道数学问题,其实并不是!
题目中说了可能会无限循环,那么也就是说求和的过程中,sum会重复出现,这对解题很重要!
如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false。
正如之前所说,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。
所以这道题目使用哈希法,来判断这sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。
判断sum是否重复出现就可以使用unordered_set。
还有一个难点就是求和的过程,如果对取数值各个位上的单数操作不熟悉的话,做这道题也会比较艰难。

②怎么获得一个数的各位数字?
一个循环里,首先对其取余10(是为了得出这个数的各位然后十位,然后百位相继得出),然后除以10(把已经得出的个位,十位,百位相继除去)。
例198,循环里,然后先对其取余,198%10=8,然后对其除以10所以198/10=19,继续循环19%10=9,19/10=1,继续循环1%10=1,1/10=0。

大致代码套路:

class Solution {
public:
    int getsum(int n){
        int sum=0;
        while(n!=0){
            sum+=(n%10)*(n%10);
            n/=10;
        }
        return sum;
    }
    bool isHappy(int n) {
       unordered_set set;
       while(n!=1){
        // getsum(n);这是错的,注意这种地方我不大会,getsum是为了得出sum,并且isHappy还没定义sum,所以需要int sum=getsum(n)
         int sum=getsum(n);
         if(sum==1){return true;}
         if(set.find(sum)!=set.end()){
             return false;
         }
         else {set.insert(sum);}
         n=sum;//注意细节题目给的n是固定的19,而你每次循环n都在变第一次19第二次82,所以还要每次循环让n=sum
       }
    }
};

两数之和题型:

http://梦开始的地方,Leetcode:1.两数之和

①为什么想到用哈希法?
这道题是找两个数和为target的,那比如target=9,比如你走到2的时候就回想前面有没有出现过7,有的话就返回这个2和7的下标嘛,再比如你走到3的时候就回想前面有没有出现过6,有的话就返回这个3和6的下标嘛,所以它是走到某个数a的时候就看前面有没有出现过target-a这个数,所以查看某个数有没有出现过,所以想到用哈希。
②为什么用map,哪个是key哪个是value?
因为你要查这两个元素之和,且返回它们下标,所以涉及元素和下标两个东西,就考虑到key和value,所以用map,set是一个集合,里面放的元素只能是一个key。因为你是要查看元素是否出现过,查看哪个是否出现过哪个就是key,判断元素是否出现,这个元素就要作为key,所以数组中的元素作为key,有key对应的就是value,value用来存下标。
③map在这道题目里是干嘛的?
是存放我们遍历过的元素的
④思路,例21736,从下标0开始遍历,遍历2,首先去查map是否有key等于7的,发现没有,然后把当前遍历的2加入到map中,再然后遍历下一个1。去查map是否有key等于8的,发现没有,然后把当前遍历的1加入到map中,再然后遍历下一个7。查看map是否有key等于2的,发现有,然后把当前2的下标和当前指针的下标返回即可。
⑤注意怎么定义map,unordered_map map;()
注意怎么往map里加入元素 : map.insert(pair(nums[i], i))
可不是简单的map.insert(nums[i],i)哇,还有pair

⑥map->first 表示的是这个元素的key的值;
map->second 表示的是这个元素的value的值。
 

大致代码套路
unordered_map map;
     for(int i=0;i         int s=target-nums[i];
        if(map.find(s)!=map.end()){
           return {map.find(s)->second,i};
            }
        else{
    map.insert (pair(nums[i],i));  //注意map.insert (pair(nums[i],i)),里面nums[i],i,是还要一个()的
          }
        }
        return {};

你可能感兴趣的:(数据结构与算法,散列表,数据结构,算法)