思路:
做过3Sum的同学看到这道题的话肯定不会感到困难, 只是在3Sum的基础上再添加一层循环, 时间复杂度O(n^3), 但是根据https://discuss.leetcode.com/topic/28641/my-16ms-c-code的机智思路, 可以在每层循环开始前做几次非常机智的判断, 如果前几个数的和就大于目标值了, 后面肯定更大了, 直接跳出循环. 如果当前值加上尾部的几个值小于目标值, 那么也不用进内层循环了, 也直接做下一次循环就好, 这样节省了大量时间, 真是学习到了! 以后要多注意剪枝
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> res;
int size = nums.size();
if (size < 4) return res;
sort(nums.begin(), nums.end());
for (int i = 0; i < size - 3; i++) {
if (i && nums[i] == nums[i - 1]) continue;
// 精髓之处
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;
//
vector<int> candidate;
for (int j = i + 1; j < size - 2; j++) {
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
// 同样精髓之处
if (nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) break;
if (nums[i] + nums[j] + nums[size - 1] + nums[size - 2] < target) continue;
//
int TwoSumTarget = target - nums[i] - nums[j];
int head = j + 1, tail = size - 1;
while (head < tail) {
if (nums[head] + nums[tail] == TwoSumTarget) {
candidate.push_back(nums[i]);
candidate.push_back(nums[j]);
candidate.push_back(nums[head]);
candidate.push_back(nums[tail]);
res.push_back(candidate);
candidate.clear();
while (head < tail && nums[head + 1] == nums[head]) head++;
while (head < tail && nums[tail - 1] == nums[tail]) tail--;
head++, tail--;
}
else if (nums[head] + nums[tail] < TwoSumTarget) head++;
else tail--;
}
}
}
return res;
}