算法训练营day7

总结

454.四数之和II

四重循环铁超时,故空间换时间,先两层循环存下来和,再两层循环查找即可;

class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        map<int,int> M;
        int n=nums1.size();
        int ans=0;

        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                M[nums1[i]+nums2[j]]++;
            }
        }

        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                int x=0-nums3[i]-nums4[j];
                if(M[x]) ans+=M[x];
            }
        }
        return ans;
    }
};

383.赎金信

只要字符M包括字符R的所有字符即可,简单来说,就是R有的M都得有,可以多不能少;
ps:随想录代码思路跟我这个一样hh

int cnt[26];
class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        memset(cnt,0,sizeof cnt);
        int lenr=ransomNote.size();
        int lenm=magazine.size();

        for(int i=0;i<lenr;i++) cnt[ransomNote[i]-'a']++;
        for(int i=0;i<lenm;i++) cnt[magazine[i]-'a']--;
        for(int i=0;i<26;i++){
            if(cnt[i]>0) return false;
        }
        return true;
    }
};

15.三数之和

这道题我是卡住了,想到了排序+双指针,没想到剩下的那个数直接暴力循环就行;

思路

1.先排序,左右指针可以确定两个数,第三个数循环确定;
2.大于0右指针–,小于0左指针++;
3.倘若第一个数就>0,可以直接返回了,这是剪枝操作;
4.去重操作有三部分,i的去重是跟前面比,防止漏过-1 -1 2类似的情况;l跟r的去重是在找到一个三元组之后;
5.找到三元组后,左右指针都移动,找下一个以i为开头的三元组;

注意

1.去重尤其注意,同一个三元组元素是可以重复的,所以去重i的时候是跟i-1比;左右指针是在找到一个三元组之后再移动;

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> ans;

        sort(nums.begin(),nums.end());
        if(nums[0]>0) return ans;

        int len=nums.size();
        for(int i=0;i<len;i++){
            if(i>0&&nums[i]==nums[i-1]) continue;
            int l=i+1,r=len-1;
            while(l<r){
                if(nums[i]+nums[l]+nums[r]>0) r--;
                else if(nums[i]+nums[l]+nums[r]<0) l++;
                else{
                    ans.push_back(vector<int>{nums[i], nums[l], nums[r]});

                    while(l<r&&nums[l]==nums[l+1]) l++;
                    while(l<r&&nums[r]==nums[r-1]) r--;
                    
                    r--;
                    l++;
                }
            }
        }
        return ans;
    }
};

18.四数之和

思路基本跟三数之和一样,这里数据范围变小,故可以来两重循环确定两个数,再左右指针确定两个数;
加和可能爆int,注意开long long;

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> ans;
        sort(nums.begin(),nums.end());

        int len=nums.size();
        for(int i=0;i<len;i++){
            if(nums[i]>target&&nums[i]>=0) break;
            if(i>0&&nums[i]==nums[i-1]) continue;
            
            for(int j=i+1;j<len;j++){
                if(nums[j]+nums[i]>target&&nums[j]+nums[i]>=0) break;
                if(j>i+1&&nums[j]==nums[j-1]) continue;

                int l=j+1;
                int r=len-1;
                while(l<r){
                    
                    if((long long)nums[i]+nums[j]+nums[l]+nums[r]>target) r--;
                    else if((long long)nums[i]+nums[j]+nums[l]+nums[r]<target) l++;
                    else{
                        ans.push_back(vector<int>{nums[i],nums[j],nums[l],nums[r]});
                        while(l<r&&nums[r]==nums[r-1]) r--;
                        while(l<r&&nums[l]==nums[l+1]) l++;
                        
                        r--;
                        l++;
                    }
                }
            }
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值