LeetCode 18. 4Sum
问题链接
题目解析
给定n元素的数组,求出满足 \(a+b+c+d = target\) 的所有元组。
解题思路
已经成为一个系列了,这道题是 LeetCode 15. 3Sum 的升级版,思路与其也是一模一样,外层再加一层循环。
先将数组排好序,便于检测重复。最外层循环固定最小数字 \(a\),第二层循环固定第二小数字 \(b\),左右指针分别代表 \(c\) 和 \(d\) ,从两边向中间移动。
注意避免重复,本题中通过判断相邻数字相等直接跳过的方法去重,米面了使用 set容器,简单易懂。
时间复杂度:\(O(n^3)\)。
参考代码
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector< vector<int> > res;
if(nums.size() < 4) return res;
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size()-3; i++) {
if(i > 0 && nums[i] == nums[i-1])//避免重复
continue;
for(int j = i+1; j < nums.size()-2; j++) {
if(j > i + 1 && nums[j] == nums[j - 1])//再次避免重复
continue;
int left = j + 1, right = nums.size() - 1;
while(left < right ) {
int sum = nums[i] + nums[j] + nums[left] + nums[right];
if(sum < target) left++;
else if(sum > target) right--;
else {
res.push_back({nums[i], nums[j], nums[left], nums[right]});
while(left + 1 < right && nums[left+1] == nums[left])//避免重复
left++;
while(right -1 > left && nums[right-1] == nums[right])//避免重复
right--;
left++; right--;
}
}
}
}
return res;
}
};
扩展
在问题讨论中看到一种效率超群的做法:7ms java code win over 100%。时间复杂度虽然也是 \(O(n^3)\),实际确实快了不少。通过将4Sum问题分解成3Sum和2Sum问题,其实就是将上述的最外两层循环分别拆成函数,添加更多的条件,可以及时判断不合理情况,从而使效率提高不少。
再深入想一想,我们见过了2Sum、3Sum和4Sum,其实可以泛化成 K-Sum 问题,找到了一篇讲的还不错的文章:k sum problem。
相似题目
LeetCode 1. Two Sum
LeetCode 15. 3Sum
LeetCode 16. 3Sum Closest
LeetCode All in One题解汇总(持续更新中...)
本文版权归作者AlvinZH和博客园所有,欢迎转载和商用,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.