day6-242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和

本文介绍了如何运用哈希表、数据结构(如数组、set、map和unordered_set)以及解决哈希冲突的方法来解决LeetCode中的四个问题,包括字母异位词判断、两个数组的交集、快乐数检测和两数之和。重点讨论了unordered_set在查询和增删效率上的优势。
摘要由CSDN通过智能技术生成

前言:此处开始使用哈希表,一般哈希表都是用来快速判断一个元素是否出现集合里

  • 哈希函数:一种映射关系,将元素映射到哈希表
  • 哈希碰撞:哈希表中多种元素都映射到同一个位置,解决方法:拉链法(链表的方式),线性探测法(找到哈希表中空闲的位置)

数据结构:

  • 数组
  • set

  • map

  • 哈希值连续或较近,范围可控,使用数组
  • 范围比较大,使用set
  • key与value对应,使用map

使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的,如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset

比较:

第一题 242.有效的字母异位词

242. 有效的字母异位词 - 力扣(LeetCode)

数组(简单哈希表)

本题的范围是26个小写字母,因此定义一个hash[26]用于存放每个字母的个数,第一个字符串出现的字母在对应位置加一,第二个字符串减一,遍历之后判断整个hash[26]是否为{0,0,0....}如果是则是异位词

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

第二题 349. 两个数组的交集

349. 两个数组的交集 - 力扣(LeetCode)

使用unordered_set 读写效率是最高的,并不需要对数据进行排序,而且还不要让数据重复,因此此题选择unordered_set

注意判断一个元素nums2[i]是否在哈希表中,应该用“if(nums1_set.find(nums2[i])!=nums1_set.end())”因为find函数返回的是迭代器的位置

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        //存放结果
        unordered_set<int> result;
        //存放去重后的第一个数组
        unordered_set<int> nums1_set(nums1.begin(), nums1.end());
        //把第二个数组的每一个元素和nums1_set比较
        for (int i = 0; i < nums2.size();i++) {
            //出现过
            if (nums1_set.find(nums2[i])!=nums1_set.end()) {
                result.insert(nums2[i]);
            }
        }
        return vector<int>(result.begin(), result.end());
    }
};

第三题 202. 快乐数

202. 快乐数 - 力扣(LeetCode)

因为可能出现无限循环,因此需要查找当前的平方和是不是在前面出现过,即判断一个元素(当前平方和)是否在集合(以前所有的的平方和)里,考虑使用哈希表,又因为不需要重复不需要有序,所以使用unordered_set

整个题的思路是先把n的各个位分离,求各个位的平方和sum,如果sum=1则是快乐数,结束程序,如果sum!=1则:

  • 如果sum不在set中,把sum存到哈希表set中(unordered_set自动去重),重复操作
  • 如果sum在set中,说明出现循环,不可能再出现和为1的情况,结束程序

由上述例子得出,要求一个数的每一个位数,先%10得到位数,再/10循环

class Solution {
public:
    bool isHappy(int n) {
        unordered_set<unsigned int>set;
        while (n) {
            //先把各个位分离
            unsigned int sum = 0;
            while (n != 0) {
                sum += (n % 10) * (n % 10);
                n = n / 10;
            }
            //是快乐数
            if (sum == 1)return true;
            //没有在set找到sum
            if (set.find(sum) == set.end()) {
                set.insert(sum);
            }
            //在set中找到了sum,进入循环
            else {
                return false;
            }
            n = sum;
        }
        return false;
    }
};

第四题 1. 两数之和 

1. 两数之和 - 力扣(LeetCode)

本题由于需要返回下标,key(存元素)和value(存下标)都需要,所以需要用map,用于快速查找key是否在map中出现过,所以key用于存元素,value用于存下标

问题:我原本的想法是使用multimap将原来的数组存入,因为本题的数组元素是可以重复的,但问题是multimap是有序的,会导致原来数组的顺序发生变化,因此不可以用

视频思路

定义一个unordered_map用于存放遍历过的元素,在map中查找target-nums[i],如果找到了则返回i和map的value值,如果没有找到则将nums[i]存放在map中,重复操作,最后如果没有找到则返回空

注意:

  • 求value值用“auto iter= map.find(target - nums[i]);”此时“iter->second”就是value值
  • map中插入时用“map.insert(pair<int,int>(nums[i],i));”
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 { i,iter->second };
            }
            else {
                map.insert(pair<int,int>(nums[i],i));
            }
        }
        return {};
    }
};
  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值