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
class Solution {
public:
typedef vector<int>::size_type sz;
vector<vector<int> > threeSum(vector<int>& nums, int target) {
vector<vector<int> > ret;
for (sz i = 0; i != nums.size() - 2; ++i) {
int twoSum = target - nums[i];
sz j = i + 1;
sz k = nums.size() - 1;
while (j < k) {
int tmpSum = nums[j] + nums[k];
if (tmpSum == twoSum) {
vector<int> tmp;
tmp.push_back(nums[i]);
tmp.push_back(nums[j]);
tmp.push_back(nums[k]);
ret.push_back(tmp);
while(j < k && nums[j + 1] == nums[j]) ++j;
++j;
while(j < k && nums[k - 1] == nums[k]) --k;
--k;
} else if (tmpSum < twoSum) {
while(j < k && nums[j + 1] == nums[j]) ++j;
++j;
} else {
while(j < k && nums[k - 1] == nums[k]) --k;
--k;
}
}
while (i + 1 != nums.size() - 2 && nums[i + 1] == nums[i]) ++i;
}
return ret;
}
vector<vector<int>> fourSum(vector<int>& nums, int target) {
if (nums.size() < 4) return vector<vector<int> >();
sort(nums.begin(), nums.end());
vector<vector<int>> ret;
for (sz i = nums.size() - 1; i != 2; --i) {
// vector<int> tmp(nums);
int tmp = nums[i];
nums.erase(nums.begin() + i);
vector<vector<int> > threeV = threeSum(nums, target - nums[i]);
if (!threeV.empty()) {
for (sz j = 0; j != threeV.size(); ++j)
threeV[j].push_back(tmp);
copy(threeV.begin(), threeV.end(), back_inserter(ret));
}
while (i - 1 != 2 && nums[i] == nums[i - 1]) {
--i;
nums.erase(nums.begin() + i);
};
}
return ret;
}
};
参考后快的不是一丢丢, 34 -> 12
The key point is to add checking at the start of the loop.
At loop 1:
if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target) break;
if(nums[i]+nums[n-3]+nums[n-2]+nums[n-1]
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
typedef vector<int>::size_type sz;
sz size = nums.size();
if (nums.size() < 4) return vector<vector<int> >();
sort(nums.begin(), nums.end());
vector<vector<int> > ret;
for (sz i = 0; i != size - 3; ++i) {
if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) break;
if (nums[i] + nums[size- 1] + nums[size - 2] + nums[size - 3] < target) continue;
for (sz j = i + 1; j != size - 2; ++j) {
int twoSum = target - nums[i] - nums[j];
sz k = j + 1;
sz m = size - 1;
if (nums[i] + nums[j] + nums[k] + nums[k + 1] > target) break;
if (nums[i] + nums[j] + nums[m] + nums[m - 1] < target) continue;
while (k < m) {
int tmpSum = nums[k] + nums[m];
if (tmpSum == twoSum) {
ret.push_back(vector<int>{nums[i], nums[j], nums[k], nums[m]});
while(k < m && nums[k + 1] == nums[k]) ++k;
++k;
while(k < m && nums[m - 1] == nums[m]) --m;
--m;
} else if (tmpSum < twoSum) {
while(k < m && nums[k + 1] == nums[k]) ++k;
++k;
} else {
while(k < m && nums[m - 1] == nums[m]) --m;
--m;
}
}
while (j + 1 != size - 2 && nums[j + 1] == nums[j]) ++j;
}
while (i + 1 != size - 3 && nums[i] == nums[i + 1]) ++i;
}
return ret;
}
};