【c++刷题笔记-哈希表】day6:454.四数相加II , 383. 赎金信 , 15. 三数之和 ,18. 四数之和

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

思路:将四个数组两两分开计算

重点:使用哈希表先记录好前两个组合的值,再通过0-(后两个组合的值)来判断是否与前两个组合匹配比如:2+1+(-1)+(-2)=0,hash[2+1]==hash[0-(-1+-2)]

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

383. 赎金信 - 力扣(LeetCode)

思路:因为ransomNote串由magazine串中的字符组成,所以当ransomNote串中出现magazine串没有的字符是表示不可以由magazine中串的字符组成,如果ransomNote串由magazine串中的字符组成表示可以由magazine中串的字符组成

重点:题目限制只有小写字母,利用数组统计magazine中每个字符的出现的次数

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        int sum[26]={0};
        for(char c:magazine){
            sum[c-'a']++;
        }
        for(char c:ransomNote){
            sum[c-'a']--;
            if(sum[c-'a']<0){
                return false;
            }
        }
        return true;
     }
};

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

思路:先排序,再用三指针方式进行搜索符合要求的三元组

重点:搜索过程中注意去重,拆解先选出第一位元素,再用双指针两端进行收缩取的合适的值

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n=nums.size();
        vector<vector<int>>ans;
        sort(nums.begin(),nums.end());//排序默认升序
        for(int i=0;i<n;i++){
            if(nums[i]>0){//最小的大于零表明不可能组成比零小的三元组
                return ans;
            }
            if(i>0&&nums[i]==nums[i-1]){//从后向前去重
                continue;
            }
            int left=i+1;
            int right=n-1;
            while(left<right){
                int sum=nums[i]+nums[left]+nums[right];
                if(sum>0){
                    right--;
                }else if(sum<0){
                    left++;
                }else{
                    ans.push_back({nums[i],nums[left],nums[right]});
                    while(left<right&&nums[right]==nums[right-1]){
                        right--;
                    }
                    while(left<right&&nums[left]==nums[left+1]){
                        left++;
                    }
                    right--,left++;//收缩双指针再寻找是否有匹配的元组
                }
            }
        }
          return ans;
    }
};

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

思路:双指针方法嵌套三重循环,搜索符合要求的值

重点:注意去重,以及边界值判断,元素相加的时候用long long接收避免溢出

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        vector<vector<int>>ans;
        int n=nums.size();
        for(int a=0;a<n-3;a++){
            long long x=nums[a];
            if(a>0&&x==nums[a-1]) continue;//去重
            if(x+nums[a+1]+nums[a+2]+nums[a+3]>target) break;
            if(x+nums[n-3]+nums[n-2]+nums[n-1]<target) continue;
            for(int b=a+1;b<n-2;b++){
                long long y=nums[b];
                if(b>a+1&&y==nums[b-1]) continue;
                if(x+y+nums[b+1]+nums[b+2]>target) break;
                if(x+y+nums[n-2]+nums[n-1]<target) continue;
                int c=b+1,d=n-1;
                while(c<d){
                    long long s=x+y+nums[c]+nums[d];
                    if(s<target)
                    c++;
                    else if(s>target){
                        d--;
                    }else {
                        ans.push_back({(int)x,(int)y,nums[c],nums[d]});
                        for(c++;c<d&&nums[c]==nums[c-1];c++);//去重
                        for(d--;d>c&&nums[d]==nums[d+1];d--);//去重
                    }
                }
            }
        }
        return ans;
    }
};

总结

哈希表能很好的解决数组元素匹配的问题发现类似的题目时可以优先考虑哈希表,遇见数组需要求匹配值且改变数组不影响后续操作的时候,优先考虑将数组进行排序和利用双指针进行求解。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值