LC18. 四数之和

题目大意

给你一个数组nums,要求找到所有不重复的和为target的四元组。

18. 四数之和

题解

和三数之和的思路一致,排序后双指针,只不过四数之和相比三数之和需要多加一个for循环,同AC代码:

class Solution {
public:
    typedef long long LL;
    int min(int a,int b,int c,int d){
        return ::min(a,::min(b,::min(c,d)));
    }

    int max(int a,int b,int c,int d){
        return ::max(a,::max(b,::max(c,d)));
    }

    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> res;
        const int sz = nums.size();
        sort(nums.begin(),nums.end());

        if(sz < 4)return res;
        if(target <= 0 && nums[0] > 0)return res;
        if(target >= 0 && nums[sz-1] < 0)return res;
        if(target > 0 && nums[0] > 0 && nums[0] > target)return res;
        if(target < 0 && nums[sz-1] < 0 && nums[sz-1] < target)return res;

        int l,r;
        for(int i = 0;i < sz; ++i){
            if(i > 0 && nums[i] == nums[i-1])continue;
            for(int j = i+1;j < sz; ++j){
                if(j > 1 && j-1 != i && nums[j] == nums[j-1])continue;
                l = j+1;
                r = sz-1;
                LL sum;
                while(l < r){
                    // int nmin = min(nums[i],nums[j],nums[l],nums[r]);
                    // int nmax = max(nums[i],nums[j],nums[l],nums[r]);
                    // if((nmin > 0 && target >= 0 && nmin >= target)
                    // || (nmax < 0 && target <= 0 && nmin <= target)
                    // || (nmax < 0 && target >= 0)
                    // || (nmin > 0 && target <= 0)){
                    //     ++l,--r;
                    //     continue;
                    // }
                    sum = (LL)nums[i] + (LL)nums[j] + (LL)nums[l] + (LL)nums[r];
                    if(sum == (LL)target){
                        res.push_back({nums[i],nums[j],nums[l],nums[r]});
                        while(l < r && nums[l] == nums[l+1])++l;
                        while(l < r && nums[r] == nums[r-1])--r;
                        --r,++l;
                    }
                    else if(sum > (LL)target)--r;
                    else if(sum < (LL)target)++l;
                }
            }
        }
        return res;
    }
};

剪枝思路

将数组排序后,对符合以下条件的样例剪枝:

  • target为负数或0,且数组首元素(排序后首元素即是数组最小值)大于0
  • target为正数或0,且数组末尾元素(即是数组最大值)小于0
  • target为正数,数组首元素为正数,且数组首元素大于target
  • target为负数,数组末尾元素为负数,且数组末尾元素小于target

上述情况均无解,可以直接返回空vector。

此外,还可以根据找出的四元组进行剪枝,即是代码中注释掉的地方,但是会引入额外的时间开销且没有必要性,所以可以不用考虑。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值