leetcode-三数之和,四数之和,n数之和的共性方法

最近leetcode也刷了100道了,开始二刷这100道题,并做每道做过题的相似题目;
leetcode的第一题是两数之和,还有三数之和,四数之和… 其实他们都可以用相同的方法来解决,甚至可以一直推到n数之和!

三数之和

在这里插入图片描述假如求两数之和,我们可以先将数组从大到小排序,然后用双指针的方法从两头往内收缩寻找:

			int i = 0;
            int j = nums.size() - 1;
            while(i<j)
            {
                if(nums[i]+nums[j] == target){
                    while(i<j&&nums[j-1] == nums[j])
                        j--;
                    while(i<j&&nums[i] == nums[i+1])
                        i++;
                    vector<int> tmp = {nums[i],nums[j]};
                    res.push_back(tmp);
                    i++;
                    j--;
                }
                else if(nums[i]+nums[j] > target)
                {
                    while(i<j&&nums[j-1] == nums[j])
                        j--;
                    j--;
                }
                else{
                    while(i<j&&nums[i] == nums[i+1])
                        i++;
                    i++;
                }
            }

这个方法的时间复杂度近似为O(n),两数之和的复杂度可以到O(n),那么三数之和的复杂度应该可以到O(n*n),我们可以固定一个数,然后对后两个数用这个两数之和的方法,还要注意去除重复!:

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> res;
        sort(nums.begin(),nums.end());
        for(int m = 0;m<nums.size();m++)
        {
            if(nums[m] > 0)
                return res;
            if(m>0&&nums[m]==nums[m-1])
                continue;
            
            int i = m+1;
            int j = nums.size() - 1;
            int target = nums[m];
            while(i<j)
            {
                if(target+nums[i]+nums[j] == 0){
                    while(i<j&&nums[j-1] == nums[j])
                        j--;
                    while(i<j&&nums[i] == nums[i+1])
                        i++;
                    vector<int> tmp = {nums[i],nums[j],target};
                    res.push_back(tmp);
                    i++;
                    j--;
                }
                else if(target+nums[i]+nums[j] > 0)
                {
                    while(i<j&&nums[j-1] == nums[j])
                        j--;
                    j--;
                }
                else{
                    while(i<j&&nums[i] == nums[i+1])
                        i++;
                    i++;
                }
            }
        }
        return res;

    }
};

四数之和

同理,我们可以先固定前两个数,然后再次使用两数之和的方法,把原本暴力法O(nnnn)降为O(nn*n)

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> res;
        sort(nums.begin(),nums.end());
        if(nums.size()<4)
            return res;
        for(int m = 0;m<nums.size()-3;m++){
            // if(nums[m]>target)
            //     return res;
            if(m>0&&nums[m] == nums[m-1])
                continue;
            for(int n = m+1;n<nums.size()-2;n++){
                // if(nums[m]+nums[n]>target)
                //     break;
                if(n>m+1&&nums[n] == nums[n-1])
                    continue;
                int i = n+1;
                int j = nums.size()-1;
                while(i<j){
                    if(nums[m]+nums[n]+nums[i]+nums[j]==target){
                        while(i<j&&nums[i]==nums[i+1]) i++;
                        while(i<j&&nums[j]==nums[j-1]) j--;
                        vector<int> tmp = {nums[m],nums[n],nums[i],nums[j]};
                        res.push_back(tmp);
                        i++;
                        j--;
                    }
                    else if(nums[m]+nums[n]+nums[i]+nums[j]>target) {
                        while(i<j&&nums[j]==nums[j-1])
                            j--;
                        j--;
                    }
                    else {
                        while(i<j&&nums[i]==nums[i+1])
                            i++;
                        i++;
                    }
                }
            }

        }
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值