Given an array S of n integers, are there elements a, b, c, 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; } };*/