地址:https://leetcode.com/problems/4sum/
题目:
Given an array nums
of n integers and an integer target
, are there elements
a
,
b
,
c
a, b, c
a,b,c, and
d
d
d in nums
such that
a
+
b
+
c
+
d
=
a + b + c + d =
a+b+c+d=target
? Find all unique quadruplets in the array which gives the sum of target
.
Note:
The solution set must not contain duplicate quadruplets.
Example:
理解:
和前面的3sum很相似。不同的就是多一层循环。
实现:
仿照着3sum写了一版,同一版代码跑出了56ms和24ms
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> res;
if (nums.empty()) return res;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); ++i) {
for (int j = i + 1; j < nums.size(); ++j) {
int target2 = target - nums[i] - nums[j];
int l = j + 1, r = nums.size() - 1;
while (l < r) {
int left = nums[l];
int right = nums[r];
if (nums[l] + nums[r] > target2) {
while (l < r&&nums[r] == right) --r;
}
else if (nums[l] + nums[r] < target2) {
while (l < r&&nums[l] == left) ++l;
}
else {
res.push_back(vector<int>{nums[i], nums[j], nums[l], nums[r]});
while (l < r&&nums[l] == left) ++l;
while (l < r&&nums[r] == right) --r;
}
}
while (j + 1 < nums.size() && nums[j + 1] == nums[j]) ++j;
}
while (i + 1 < nums.size() && nums[i + 1] == nums[i]) ++i;
}
return res;
}
};
看了submission里有一种8ms的方法,针对现在的方法做了一些优化,感觉挺好的。
大概思路就是
- 如果循环到了目前的位置,最近的四个元素之和都大于target的话,后面的肯定更大,直接break;
- 如果目前位置最前和最后的和小于target,说明后面更新的肯定更小,直接continue就可以了,避免重复计算
- 没有的话,就说明前四个之和小于target,但是首尾之和大于target,中间可能存在等于的。再寻找
按这个思路优化,代码如下:
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> res;
if (nums.empty()) return res;
int n=nums.size();
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); ++i) {
if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target) break;
if(nums[i]+nums[n-1]+nums[n-2]+nums[n-3]<target) continue;
for (int j = i + 1; j < nums.size(); ++j) {
if(nums[i]+nums[j]+nums[j+1]+nums[j+2]>target) break;
if(nums[i]+nums[j]+nums[n-1]+nums[n-2]<target) continue;
int target2 = target - nums[i] - nums[j];
int l = j + 1, r = nums.size() - 1;
while (l < r) {
int left = nums[l];
int right = nums[r];
if (nums[l] + nums[r] > target2) {
while (l < r&&nums[r] == right) --r;
}
else if (nums[l] + nums[r] < target2) {
while (l < r&&nums[l] == left) ++l;
}
else {
res.push_back(vector<int>{nums[i], nums[j], nums[l], nums[r]});
while (l < r&&nums[l] == left) ++l;
while (l < r&&nums[r] == right) --r;
}
}
while (j + 1 < nums.size() && nums[j + 1] == nums[j]) ++j;
}
while (i + 1 < nums.size() && nums[i + 1] == nums[i]) ++i;
}
return res;
}
};