数据结构与算法学习day10-哈希表-快乐数、两数之和、四数相加 II

一、快乐数

1.题目

202. 快乐数 - 力扣(LeetCode)

2.思路

  • 首先得从每个位置上进行取数平方运算。
  • 为了避免进入循环,可以用unordered_set的数据类型对计算过的sum进行存储后,方便后面判断sum是否重复出现(insert、find函数的利用)

3.代码

class Solution {
public:
    //计算每个位置上的平方,默认是输入两位
    int getsum(int n){
        int sum = 0;
        //先从低位开始处理
        while(n){
            sum = sum + (n%10)*(n%10);
            n = n / 10;
        }
        return sum;
    }

    bool isHappy(int n) {
        unordered_set<int> num;//用来存储计算过数,防止进入循环
        int sum;
        while(1){
            sum = getsum(n);
            //跳进了循环,直接退出
            if(num.find(sum) != num.end()){
                return false;
            }
            else if(sum == 1){
                return true;
            }
            else{
                num.insert(sum);
                n = sum;
            }
        }
    }
};

二、两数之和

1.题目

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

2.思路

1.如果不用两次for循环怎么做?

看第一个元素的时候,必会向后面元素查找是否有合适的值,找到后然后一起返回坐标(这种就相当于两次遍历)。两层for循环查找,时间复杂度是O(n^2)。

为了降低时间复杂度,可以使用unordered_map类型:1.可以存放key、value值 2.遍历时间复杂低遍历数组元素时,再查找map的key,如果满足,则返回两者的下标值。不满足,则把数组元素插入到map当中,继续进行数组遍历,直到最后。

2.为什么会想到用哈希表?为什么要用map?

map目的用来存放我们访问过的元素,因为遍历数组的时候,需要记录我们之前遍历过哪些元素和对应的下标,这样才能找到与当前元素相匹配的(也就是相加等于target)

这道题 我们需要 给出一个元素,判断这个元素是否出现过,如果出现过,返回这个元素的下标。

那么判断元素是否出现,这个元素就要作为key,所以数组中的元素作为key,有key对应的就是value,value用来存下标。所以 map中的存储结构为 {key:数据元素,value:数组元素对应的下标}。

3.第一次用map需要注意的点是什么?

用对应的value值、插入值

3.代码

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> gather;//定义map来存放之前遍历过的数组元素
       
        for(int i=0;i < nums.size();i++){
             int s = target - nums[i];
            if(gather.find(s) != gather.end()){
                return {gather.find(s)->second,i};//通过key值找对应的下标
            }
            gather.insert(pair<int,int>(nums[i],i));//插入之前遍历过且不符合条件的数组元素
        }
        return {};
    }
};

三、四数相加 II

1.题目

454. 四数相加 II - 力扣(LeetCode)

2.思路

官方思路:

我们可以将四个数组分成两部分,A 和 B 为一组,C 和 D 为另外一组。

对于 A 和 B,我们使用二重循环对它们进行遍历,得到所有 A[i]+B[j] 的值并存入哈希映射中。对于哈希映射中的每个键值对,每个键表示一种 A[i]+B[j],对应的值为 A[i]+B[j] 出现的次数。

对于 C 和 D,我们同样使用二重循环对它们进行遍历。当遍历到 C[k]+D[l] 时,如果 −(C[k]+D[l]) 出现在哈希映射中,那么将 −(C[k]+D[l]) 对应的值累加进答案中。

最终即可得到满足 A[i]+B[j]+C[k]+D[l]=0 的四元组数目。

3.代码

class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        unordered_map<int,int> map;
        for(auto a:nums1){
            for(auto b:nums2){//统计a+b的值出现的次数
                map[a+b]++;
            }
        }
        int count=0;
        for(auto c:nums3){
            for(auto d:nums4){
                if(map.find(0-(c+d)) != map.end()){
                    count += map[0-(c+d)];
                }
            }
        }
        return count;
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值