[代码随想录07]哈希表的进阶巧妙操作,四数相加,赎金信,三数之和

前言

哈希表的进阶操作,更加多维的方式去思考哈希表在实际中的应用,但是我们需要判断这个操作的可行性,是否有更好的思路去解决这个问题!

题目链接

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

383. 赎金信 - 力扣(LeetCode)

15. 三数之和 - 力扣(LeetCode)

18. 四数之和 - 力扣(LeetCode)

一、四数相加

 思路:刚开始一看题目,我就只能想到N^4的时间复杂度,然后想着借鉴三数之和,四数之和的思路,去固定数去找其他数,但是人家在一个数组容器里面,接着看题解,没想到还可以用哈希表来暂存中间的变量,达到用o^2的空间去换o^2的时间的目的,

int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
    unordered_map<int,int>umap;
    for(int a:nums1){
       for(int b:nums2){
            umap[a+b]++;
        }
    }
    int count=0;
    for(int c:nums3){
        for(int d:nums4){
            if(umap.find(0-(c+d))!=umap.end()){
               count+=umap[0-(c+d)];
            }
        }
   }
   return count;
}

二、赎金信

 思路:和字母异位的思路是一样的,只不过,这次改了一个逻辑点就是判断一下是否小于0.

bool canConstruct(string ransomNote, string magazine) {
        int ans[26];
        for(auto i:magazine){
            ans[i-'a']++;
        }
        for(auto i:ransomNote){
            ans[i-'a']--;
            if(ans[i-'a']<0) return false;
        }
        return true;
    }

三、三数之和

 思路:定义结果集,然后排序使用双指针操作,主要是去固定数据,这里主要是想引入哈希的方法去去重,这个思路是没有问题的,不过实现的逻辑有点复杂。主流方法还是双指针

vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>>res;
        sort(nums.begin(),nums.end());
        for(int i=0;i<nums.size();i++){
            if(nums[i]>0)break;
            if(i>0&&nums[i]==nums[i-1])continue;
            unordered_set<int>set;
            for(int j=i+1;j<nums.size();j++){
                if(j>i+2&&nums[j]==nums[j-1]&&nums[j-1]&&nums[j-2])continue;
                int c=0-(nums[i]+nums[j]);
                if(set.find(c)!=set.end()){
                    res.push_back({nums[i],nums[j],c});
                    set.erase(c);
                }else{
                    set.insert(nums[j]);
                }
            }
        }
        return res;
    }
//双指针的做法
vector<vector<int>> threeSum(vector<int>& nums) {
        ranges::sort(nums);
        vector<vector<int>>ans;
        int n=nums.size();
        for(int i=0;i<n;i++){
            int x=nums[i];
            if(nums[i]>0)break;
            if(i&&x==nums[i-1])continue;
            int j=i+1,k=n-1;
            while(j<k){
                int s=x+nums[j]+nums[k];
                if(s>0)k--;
                else if(s<0)j++;
                else {
                    ans.push_back({x,nums[j],nums[k]});
                    while(j++,j<k&&nums[j]==nums[j-1]);j++;
                    while(k--,k>j&&nums[k]==nums[k+1]);k--;
                }
            }
        }
        return ans;
    }

四、四数之和

 思路:同理,这里直接介绍双指针的做法吧

vector<vector<int>> fourSum(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());//排序
        vector<vector<int>> ret;//结果
        int n=nums.size();//长度
        for(int i=0;i<n;){
            for(int j=i+1;j<n;){
                int left=j+1,right=n-1;
                long long aim=(long long)target-nums[i]-nums[j];
                while(left<right){
                    int sum =nums[left]+nums[right];
                    if(sum<aim)left++;
                    else if(sum>aim)right--;
                    else{
                        ret.push_back({nums[i],nums[j],nums[left++],nums[right--]});
                        while(left<right&&nums[left]==nums[left-1])left++;
                        while(left<right&&nums[right]==nums[right+1])right--;
                    }
                }
                j++;
                while(j<n&&nums[j]==nums[j-1])j++;
            }
            i++;
            while(i<n&&nums[i]==nums[i-1])i++;
        }
        return ret;
    }

总结

哈希表的主要用法就是去重,牺牲空间建立索引去直接查找一个数!,希望兄弟们在接着刷题的过程中,能结合前面的一些方法形成自己的做题技巧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值