LeetCode题解——4SUm

Given an array S of n integers, are there elements abc, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:

  • Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
  • The solution set must not contain duplicate quadruplets.

    For example, given array S = {1 0 -1 0 -2 2}, and target = 0.

    A solution set is:
    (-1,  0, 0, 1)
    (-2, -1, 1, 2)
    (-2,  0, 0, 2)
//类似于3Sum,固定2个数,另两个数为lo,hi遍历,使用技巧剪枝 pruning,可使得运算速度大大加快,O(n^3),实际远小于O(n^3)
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> ans;
        if(nums.size()<4)  return ans;
     
        sort(nums.begin(),nums.end());
        
        int lo,hi;
        int MaxSize = nums.size();//可能组成4Sum的最大数字;
        for(int i=0; i<MaxSize-3; i++)
        {
            if(nums[i]+nums[MaxSize-1]+nums[MaxSize-2]+nums[MaxSize-3]<target) continue;//pruning is so magic
            if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target) break;//pruning is so magic
            if(nums[i]+nums[i+1]+nums[i+2]+nums[MaxSize-1]>target) MaxSize--;//更新MaxSize,注意边界情况的剪枝
            for(int j=i+1; j<MaxSize-2;j++)
            {
                if(nums[i]+nums[j]+nums[MaxSize-1]+nums[MaxSize-2]<target) continue;
                if(nums[i]+nums[j]+nums[j+1]+nums[j+2]>target) break;
                
                lo = j+1;
                hi = MaxSize-1;
                int want = target-nums[i]-nums[j];
                while(lo<hi)
                {
                    if(nums[lo]+nums[hi]==want)
                        {
                            vector<int> tm;
                            tm.push_back(nums[i]);
                            tm.push_back(nums[j]);
                            tm.push_back(nums[lo]);
                            tm.push_back(nums[hi]);
                            ans.push_back(tm);
                            while(lo<hi&&nums[lo]==nums[lo+1]) lo++;
                            while(lo<hi&&nums[hi]==nums[hi-1]) hi--;
                            lo++;
                            hi--;
                        }
                    else if(nums[lo]+nums[hi]>want) hi--;
                    else lo++;
                }
                while(nums[j]==nums[j+1]) j++;
            }
            while(nums[i]==nums[i+1]) i++;
        }
        return ans;
    }
};

/*class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>>  result;
        if(nums.size() < 4) return result;

        vector<int> solution(4,0);
        std::sort(nums.begin(),nums.end());
        int sum,a,b,c,d,Max_d_when_a_increase = nums.size() - 1,Max_d_when_b_increase;

        //a,b,c,d are the four index
        //Max_d_when_a_increase is the max possible d when a increase. To have the same sum, when a increase, d can only decrease
        //Max_d_when_b_increase is the max possible d when b increase

        for( a = 0; a < Max_d_when_a_increase - 2;a++ )
        {
            //remove dupilcate & pruning if a too small or too big
            if((a>0 && nums[a] == nums[a-1])
            || nums[a] + nums[Max_d_when_a_increase] + nums[Max_d_when_a_increase-1] + nums[Max_d_when_a_increase-2] < target) continue;
            if(nums[a]+nums[a+1]+nums[a+2]+nums[a+3] > target) break;            

            //update Max_d_when_a_increase
            sum = nums[a]+nums[a+1]+nums[a+2];
            while(sum+nums[Max_d_when_a_increase] > target)Max_d_when_a_increase--;
            Max_d_when_b_increase = Max_d_when_a_increase;

            solution[0] = nums[a];
            for( b=a+1; b < Max_d_when_b_increase - 1;b++)
            {
                //remove dupilcate & pruning if b too small or too big
                if((b>a+1 && nums[b] == nums[b-1])
                || nums[a] + nums[b] + nums[Max_d_when_b_increase-1] + nums[Max_d_when_b_increase] < target) continue;
                sum = nums[a] + nums[b]+nums[b+1];
                if(sum + nums[b+2] > target) break;

                //update Max_d_when_b_increase
                while(sum+nums[Max_d_when_b_increase]>target) Max_d_when_b_increase--;

                solution[1] = nums[b];
                c = b+1;
                d = Max_d_when_b_increase;
                sum = nums[a] + nums[b];
                while(c < d)//this are the same as two sum
                    if(sum + nums[c] + nums[d] == target)
                    {
                        solution[2]=nums[c];
                        solution[3]=nums[d];
                        result.push_back(solution);

                        do{c++;}while(c < d && nums[c] == nums[c-1]);
                        do{d--;}while(c < d && nums[d] == nums[d+1]);
                    }
                    else if(sum + nums[c] + nums[d] < target) 
                        do{c++;}while(c < d && nums[c] == nums[c-1]);
                    else do{d--;}while(c < d && nums[d] == nums[d+1]);
            }
        }
        return result;
    }
};*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值