算法小白,最近刷LeetCode。希望能够结合自己的思考和别人优秀的代码,对题目和解法进行更加清晰详细的解释,供大家参考^_^
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.
Note: The solution set must not contain duplicate quadruplets.
For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0.
A solution set is:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
题目意思很清晰,找到所有不重复的四元组,使其和为给定的target
之前做过三个数和的问题(LeetCode 15. 3Sum),参考之前的思路,下意识的以为有O(n^2 * log n)的算法,即按照3Sum的方法找到前三个数的和,再二分查找第四个数就行。再仔细想了一下,发现是不对的,在3Sum问题中,三个数的和是给定的,也就是只有一种情况。在本题中,三个数的和可以有n-1种情况,对每种情况都进行3Sum问题的求解方式,实际的复杂度是O(n^3)
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
size_t len = nums.size();
sort (nums.begin(), nums.end()); // 排序
vector<vector<int> > vii;
for (int i = len - 1; i >= 3; --i){
int sum3 = target - nums[i]; // 选定第四个数
for (int j = i - 1; j >= 2; --j){
int sum2 = sum3 - nums[j]; // 选定第三个数
int beg = 0, end = j - 1;
while (beg < end){ // 两个指针指向第一个数和第二个数
int tmp_sum = nums[beg] + nums[end];
if (tmp_sum > sum2) --end;
else if (tmp_sum < sum2) ++beg;
else {
vector<int> vs({nums[beg], nums[end], nums[j], nums[i]});
vii.push_back(vs);
// 对前两个数进行去重
while (beg < end && nums[beg] == nums[++beg]);
while (beg < end && nums[end] == nums[--end]);
}
}
while (j >= 2 && nums[j] == nums[j-1]) --j; // 对第三个数进行去重
}
while (i >= 3 && nums[i] == nums[i-1]) --i; // 对第四个数进行去重
}
return vii;
}
};
提交之后,还以为会超时,结果AC了,用时也击败了79%的方案,大致瞟了眼用时最短的代码,貌似也是O(n^3)的复杂度,只是提前对某些不可能的情况进行了处理。
还没查资料,不知道这类题最小的时间复杂度是多少,还有就是扩展到n分元素求和的情况,它的时间复杂度又会是多少