【Leetcode刷题记录】18.四数之和
18. 四数之和
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重
复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
这道题的解题思路和15. 三数之和是类似的,或者说就是三数之和。首先对数组nums
进行排序,遍历数组中的元素nums[i]
将其作为潜在的四元组的第一个元素,那么对于nums[i]
后面的所有元素,可以看做另一个数组tempnums
,在数组tempnums
中寻找不重复的三元组使其满足tempnums[a]+tempnums[b]+tempnums[c]==target-nums[i]
,那么这不就是15. 三数之和吗?
代码
vector<vector<int>> fourSum(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int n = nums.size();
vector<vector<int>> res;
for (int i = 0; i < n - 3; i++) {
if (i > 0 && nums[i - 1] == nums[i])
continue;
for (int j = i + 1; j < n - 2; j++) {
if (j > i + 1 && nums[j] == nums[j - 1])
continue;
int l = j + 1, r = n - 1;
while (l < r) {
long sum = static_cast<long>(nums[i]) + nums[j] + nums[l] +
nums[r]; // 防止溢出
if (sum < target) {
l += 1;
} else if (sum > target) {
r -= 1;
} else {
res.push_back({nums[i], nums[j], nums[l], nums[r]});
// 去重
while (l < r && nums[l] == nums[l + 1]) {
l += 1;
}
while (l < r && nums[r] == nums[r - 1]) {
r -= 1;
}
l += 1;
r -= 1;
}
}
}
}
return res;
}
同样的,这里还有类似的提前终止条件,也就是:
- 最小值大于目标值,跳出循环
- 最大值小于目标值,跳过本次循环
完善后的代码如下:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int n = nums.size();
vector<vector<int>> res;
for (int i = 0; i < n - 3; i++) {
if (i > 0 && nums[i - 1] == nums[i])
continue;
// 提前终止
if ((long)nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] >
target)
break;
if ((long)nums[i] + nums[n - 3] + nums[n - 2] + nums[n - 1] <
target)
continue;
for (int j = i + 1; j < n - 2; j++) {
if (j > i + 1 && nums[j] == nums[j - 1])
continue;
// 提前终止
if ((long)nums[i] + nums[j] + nums[j + 1] + nums[j + 2] >
target)
break;
if ((long)nums[i] + nums[j] + nums[n - 2] + nums[n - 1] <
target)
continue;
int l = j + 1, r = n - 1;
while (l < r) {
long sum = static_cast<long>(nums[i]) + nums[j] + nums[l] +
nums[r]; // 防止溢出
if (sum < target) {
l += 1;
} else if (sum > target) {
r -= 1;
} else {
res.push_back({nums[i], nums[j], nums[l], nums[r]});
// 去重
while (l < r && nums[l] == nums[l + 1]) {
l += 1;
}
while (l < r && nums[r] == nums[r - 1]) {
r -= 1;
}
l += 1;
r -= 1;
}
}
}
}
return res;
}