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

哈希表是一种能实现快速访问的数据结构,常用于判断元素是否存在。哈希函数将关键码值映射为索引,实现O(1)的查找效率。文章讨论了哈希碰撞的处理方法,如拉链法和线性探测法,并列举了几种常见的哈希结构,如数组、set、map及其变体。此外,还展示了哈希表在有效字母异位词判断、两数之和、数组交集及快乐数问题等算法中的应用。
摘要由CSDN通过智能技术生成

哈希表理论基础

哈希表是根据关键码的值而直接进行访问的数据结构。
代码随想录上给的例子:

那么哈希表能解决什么问题呢,一般哈希表都是用来快速判断一个元素是否出现集合里。

例如要查询一个名字是否在这所学校里。
要枚举的话时间复杂度是O(n),但如果使用哈希表的话, 只需要O(1)就可以做到。
我们只需要初始化把这所学校里学生的名字都存在哈希表里,在查询的时候通过索引直接就可以知道这位同学在不在这所学校里了。
将学生姓名映射到哈希表上就涉及到了 hash function ,也就是哈希函数
哈希函数

哈希函数,把学生的姓名直接映射为哈希表上的索引,然后就可以通过查询索引下标快速知道这位同学是否在这所学校里了。

哈希函数如下图所示,通过hashCode把名字转化为数值,一般hashcode是通过特定编码方式,可以将其他数据格式转化为不同的数值,这样就把学生名字映射为哈希表上的索引数字了。

哈希碰撞 Collisions
拉链法
  • 冲突

线性探测法
  • 保证tableSize>dataSize

常见的三种哈希结构
  • 数组

  • set - O(log n)

  • map - O(log n)

| set | 红黑树 | 有序 | 不可有重复数值 | 不能更改数值 |

| multiset | 红黑树 | 有序 | 可以有重读数值 | 不可更改数值 |

| unordered_set | 哈希表 | 无序 | 不可有重复数值 | 不可更改数值 |

| map | 红黑树 | key有序 | key不可重复 | key不可修改 |

| multimap | 红黑树 | key有序 | key可重复 | key不可修改 |

| unordered_map | 哈希表 | key无序 | key不可重复 | key不可修改 |

242.有效的字母异位词 Valid Anagram

  • 先遍历s字符串中的字符进行查数并放在查数的数组里(有几个字符那么对应的查数数组+1)

  • 再遍历t字符串中的字符进行查数,并减去已有的.

  • 最后对比查数数组,如果为0则true,不为0则是false.

class Solution {  
public:  
    bool isAnagram(string s, string t) {  
        int order[26] = {0};  
        for (int i = 0; i < s.size(); i++){  
            order[s[i]-'a']++;  
        }  
        for (int i = 0; i < t.size(); i++){  
            order[t[i]-'a']--;  
        }  
  
        for (int i = 0; i < 26; i++){  
            if (order[i] != 0){  
                return false;  
            }  
        }  
        return true;  
    }  
};

349. 两个数组的交集 Intersection of Two Array

  • nums<=1000 用数组比set做这道题更好

  • 这题用unorder_set做,输出结果需要去重.

直接插入到set中: unordered_set<int> nums_set(nums1.begin(),nums1.end());

查找的话需要不等于set的尾: if (nums_set.find(num) != nums_set.end())

class Solution {  
public:  
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {  
        unordered_set<int> result_set;  
        unordered_set<int> nums_set(nums1.begin(),nums1.end());  
        for (int num : nums2){  
            if (nums_set.find(num) != nums_set.end()){  
                result_set.insert(num);  
            }  
        }  
        return vector<int>(result_set.begin(),result_set.end());  
    }  
};

202.快乐数 Happy Number

  • 要么结果为1,要么是一个一直循环的数.

  • 当在hashset里查找会不会有循环里出现过的数字. if (set.find(temp) != set.end())

  • 如果赶回一个set里有过的数字会直接返回false,因为set里数字不能重复.

class Solution {  
public:  
    bool isHappy(int n) {  
        unordered_set<int> set;  
  
        while (n != 1){  
            int temp = 0;  
            while (n != 0){  
                int digit = n % 10;  
                temp += digit * digit;  
                n /= 10;  
            }  
  
            if (set.find(temp) != set.end()){  
                return false;  
            } else {  
                set.insert(temp);  
            }  
            n = temp;  
        }  
        return true;  
    }  
};

1. 两数之和

  • 用map是最好的解法, 可以直接保存下标.

  • 首先拿target减去现在的数,进行查找,找到了直接输出下标.

  • map.insert(pair<int,int>(nums[i],i)) 也可以写成 map[nums[i]] = i

class Solution {  
public:  
    vector<int> twoSum(vector<int>& nums, int target) {  
        std::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};  
            }  
            map.insert(pair<int,int>(nums[i],i));  
        }  
        return {};  
    }  
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Stark_Ye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值