算法学习day6

1. 哈希表理论基础

1.哈希表基础.
哈希表是根据关键码的值直接访问的数据结构。
例:数组,数组下标(关键码)。通过下标直接访问数组中的元素。
一般哈希表都是用来快速判断一个元素是否出现在集合里。
2.哈希函数.
例:哈希函数,可以将学生的姓名直接映射为哈希表上的索引,通过查询索引下标可以知道同学是否在这所学校里。
在这里插入图片描述
3.哈希碰撞.
在这里插入图片描述
图片来源:代码随想录

2. 力扣242题-有效的字母异位词

2.1 分析

1.数组是一个简单的哈希表,题目中字符串不含有大写。定义一个大小为26的数组来统计。
2.首先将26个字母映射成数字当做数组的下标来统计数量。s[i] - ‘a’,a-z用下标索引0-25表示。同时将索引对应的元素的值加1.
3.同理统计第二字符串并将索引对应的元素减1.
4.最后循环遍历数组,如果存在有不为0的数值。说明字符串s、t,不相同(指的是内容不同)、位置无关。否则说明为有效的字母异位词。

2.2 代码

class Solution {
public:
    bool isAnagram(string s, string t) {
        int num[26] = {0};
        //将26个字母映射成数字当做数组的下标统计数量
        for(int i = 0 ; i < s.size() ; i++){
            num[s[i]-'a']++;
        }
        //统计第二个字符串,并减1
        for(int i = 0 ; i < t.size() ; i++){
            num[t[i]-'a']--;
        }
        //若为有效的字母异位词数组必全为零,若出现其他值,必为false
        for(int i = 0 ; i < 26 ; i++){
            if(num[i] !=0){
                return false;
            }
        }
        return true;
    }
};

3. 力扣349题-两个数组的交集

3.1 分析

1.std::set、std::multiset底层实现是红黑树。std::unordered_set底层实现是哈希表。使用unordered_set读写效率最高,且不需要对数据进行排序。
2.定义一个result的set哈希表,存放最后要返回的结果,因为unordered_set可以在插入元素的时候自动去重。
3.将nums1中的元素放入另外一个unordered_set nums_set中,去重。
4.遍历nums2中的元素,若发现元素在nums_set中也存在,将该元素插入到result中。
5.遍历结束将result转换回vector.

3.2 代码

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result;
        unordered_set<int> nums_set(nums1.begin(),nums1.end());

        for(int i = 0 ; i < nums2.size() ; i++){
            //如果nums2[i]元素不存在集合nums_set中,返回迭代器nums_set.end()
            if(nums_set.find(nums2[i]) != nums_set.end()){
                //不用考虑去重操作了
                result.insert(nums2[i]);
            }
        }
        return vector<int>(result.begin(),result.end());
    }
};

4. 力扣202题-快乐数

4.1 分析

1.关键点:当重复出现就不是快乐数了。

4.2 代码

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) {
        //快速判断一个元素是否出现在集合里,用哈希法
        //当sum重复说明不是快乐数
        unordered_set<int> set;
        while(1){
            int sum = getSum(n);
            //如果上来直接就找到了
            if(sum == 1){
                return true;
            }
            //如果这个sum重复出现,陷入死循环,说明不是快乐数
            if( set.find(sum) != set.end()){
                return false;
            }else{
                set.insert(sum);
            }
            n = sum;//更新,用新数值,继续求平方和,检测是否快乐数
        }
    }
};

5. 力扣1题-两数之和

5.1 分析

1.当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法。
2.key来存放元素,value来存放下标,使用map刚刚好.
3.遍历nums数组,目标值减去当前遍历到的数组。剩余的数在map中找(利用相减可以找到满足目标值的两个数字)。若找到:直接返回,没有找到往map里面存。
在这里插入图片描述
在这里插入图片描述
图片来源:代码随想录

5.2 代码

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> map;
        for(int i = 0 ; i < nums.size() ; i++){
            //在map中找,目标值-元素 含有。若存在返回
            //map 中键(key)存放元素 值(valur)存放下标
            if(map.find(target - nums[i]) != map.end()){
                return {map.find(target - nums[i])->second,i};
            }
            //在map中找,目标值-元素 不含有。插入map中
            else{
                map.insert(pair<int,int>(nums[i],i));
            }
        }
        //没找到返回空
        return {};
    }
};

6.参考资料

代码随想录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值