代码随想录(第六天)|哈希表|有效的字母异位词|两个数组的交集|快乐数|两数之和

文章目录

  • 哈希表
    • 哈希函数
    • 哈希碰撞
      • 拉链法
      • 线型探测法
    • 常见哈希结构
    • 有效的字母异位词
      • 暴力解法
      • 哈希表
    • 两个数组的交集
      • 暴力解法
      • 哈希表
    • 快乐数
    • 两数之和

哈希表

用来快速判断一个元素是否出现集合里

哈希函数

一种映射方式

哈希碰撞

多个数据映射到同一个表格中,即哈希表不够大。
解决方法。

拉链法

代码随想录(第六天)|哈希表|有效的字母异位词|两个数组的交集|快乐数|两数之和_第1张图片

线型探测法

tableSize大于dataSize,发生了冲突,就使用下一个空位

常见哈希结构

数组,set(集合),map(映射)

有效的字母异位词

https://leetcode.cn/problems/valid-anagram/

暴力解法

可以使用sort

class Solution {
public:
    bool isAnagram(string s, string t) {
        if (s.length() != t.length()) {
            return false;
        }
        sort(s.begin(), s.end());
        sort(t.begin(), t.end());
        return s == t;
    }
};

或者统计每个字符出现次数

哈希表

class Solution {
public:
    bool isAnagram(string s, string t) {
        int hash[26] = {0};
        int st ='a';
        int loc;
        int flag=0;

        for(int i =0;i<s.size();i++){
            loc = s[i]-st;
            hash[loc] ++;
        }

        for(int j=0;j<t.size();j++){
            loc = t[j]-st;
            hash[loc] --;
        }
       for(int k=0;k<26;k++){
         if(hash[k]!=0)
         {
         flag = 1;
         break;
         }
       }
       if(flag==0)
       return true;
       else
       return false;
    }
};

后面的判断可以简化,不需要flag直接返回就行。基本思路如下图代码随想录(第六天)|哈希表|有效的字母异位词|两个数组的交集|快乐数|两数之和_第2张图片

两个数组的交集

https://leetcode.cn/problems/intersection-of-two-arrays/solution/

暴力解法

  • 使用到vector的特性,使用了push_back函数

哈希表

使用std::unordered_set结构(set结构没有重复)

代码随想录(第六天)|哈希表|有效的字母异位词|两个数组的交集|快乐数|两数之和_第3张图片
具体使用方法

https://blog.csdn.net/qq_40286920/article/details/124731777

for(int num :nums2)是 C++11引入的范围-based for 循环语句,也称为foreach 循环。这段代码的意思是对一个容器(如数组、向量、列表等)进行遍历,其中nums2是一个容器,num 是循环迭代的变量名,表示容器中的每个元素的值。在循环的每次迭代中,num 会被赋值为容器中的下一个元素,直到遍历完所有元素。

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result_set; // 存放结果,之所以用set是为了给结果集去重
        unordered_set<int> nums_set(nums1.begin(), nums1.end());
        for (int num : nums2) {
            // 发现nums2的元素 在nums_set里又出现过
            if (nums_set.find(num) != nums_set.end()) {
                result_set.insert(num);
            }
        }
        return vector<int>(result_set.begin(), result_set.end());
    }
};

代码的思路不难,麻烦的是语法。

快乐数

https://leetcode.cn/problems/happy-number/

核心是出现重复,即如果出现循环,且不为1,则不是快乐数。所以同样采用哈希表。

class Solution {
public:
    int getsum(int n){
    int sum=0;
    while(n){
        sum+=(n%10)*(n%10);
        n=n/10;
    }
    return sum;
    }

    bool isHappy(int n) {

    unordered_set <int> set;
    int sum=0;

    while(1){
        sum = getsum(n);
        if(sum ==1){
            return true;

        }
        if(set.find(sum)!=set.end()){
            return false;
        }
        else{
            set.insert(sum);
        }
        n = sum;
    }

    }
};
  • unordered_set用到了#unordered_set
  • 同样,尽量画图整理逻辑,不然容易在判断时出错

两数之和

https://leetcode.cn/problems/two-sum/

之前的set无法存储下标,只能存储key。所以现在需要使用新结构map,使用 key value结构来存放,key来存元素,value来存下标。

我们使用std::unordered_map,其主要用法:

https://blog.csdn.net/xiaoyu_wu/article/details/121490312

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> map;

        for(int i=0;i<nums.size();i++){
            auto iter = map.find(target-nums[i]);
            if (iter!=map.end()){
                return {iter->second,i};
            }
            else
            map.insert(pair<int,int> (nums[i],i));
        }
        return {};
    }
};
  • auto:初始化可为任何表达式,即可自动变为int等类型。iter在这里是一个迭代式。
  • iter->second具体用法见引用,此时返回下标
  • map.insert(pair (nums[i],i));也可使用 map[nums[i]]=i
  • {}表示数组

你可能感兴趣的:(散列表,哈希算法,leetcode)