2019.1.29
题目描述:
Given an array nums
of n integers and an integer target
, are there elements a, b, c, and d in nums
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.
Example:
Given array nums = [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] ]
这题算是求三数之和的升级版,变成了求四数之和,不过思想上基本上还是一样的,先固定前两个数,再线性遍历后两个数取和即可,也就是多了一层循环而已。因为要求返回不重复的数组,所以这里我们使用C++中STL的set来去重。
解法一:用set去重
C++代码:
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
set<vector<int>> res;
int temp;
sort(nums.begin(),nums.end());
for(int i=0;i<int(nums.size()-3);i++){
for(int j=i+1;j<int(nums.size()-2);j++){
if(j>i+1&&nums[j]==nums[j-1]) continue;
int m=j+1,n=nums.size()-1;
while(m<n){
temp=nums[i]+nums[j]+nums[m]+nums[n];
if(temp==target){
vector<int> out={nums[i], nums[j], nums[m], nums[n]};
res.insert(out);
m++;n--;
}else if(temp<target)m++;
else n--;
}
}
}
return vector<vector<int>>(res.begin(), res.end());
}
};
时间复杂度:O(n^3)
有几个要注意的点:
1.我们用set去重,但是最后需要返回vector<vector<int>>类型。
2.开始我在i,j的范围用的是nums.size()-3,nums.size()-2,但是有个测试用例没有通过,即输入为[ ]时,后来几经查阅,终于明白了,因为nums.size()是unsigned int,当nums.size()为0时,nums.size()-2就为2^32-2,循环次数太多了,直接超了。
看评论有不用set直接手动去重的,我就直接贴一下吧。
解法二:手动去重
C++代码:
class Solution {
public:
vector<vector<int>> fourSum(vector<int> &nums, int target) {
vector<vector<int>> res;
int n = nums.size();
sort(nums.begin(), nums.end());
for (int i = 0; i < n - 3; ++i) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
for (int j = i + 1; j < n - 2; ++j) {
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
int left = j + 1, right = n - 1;
while (left < right) {
int sum = nums[i] + nums[j] + nums[left] + nums[right];
if (sum == target) {
vector<int> out{nums[i], nums[j], nums[left], nums[right]};
res.push_back(out);
while (left < right && nums[left] == nums[left + 1]) ++left;
while (left < right && nums[right] == nums[right - 1]) --right;
++left; --right;
} else if (sum < target) ++left;
else --right;
}
}
}
return res;
}
};
时间复杂度:O(n^3)
Follow Up:
评论里直接贴出了kSum的代码,我看了,挺好的,直接贴出了吧,这类题目思想还是一样的。
C#代码:
public class Solution
{
private int _len;
public IList<IList<int>> FourSum(int[] nums, int target) {
_len = nums.Length;
nums = nums.OrderBy(n => n).ToArray();
return KSum(nums, target, 4, 0);
}
private IList<IList<int>> KSum(int[] nums, int target, int k, int index)
{
var res = new List<IList<int>>();
if (index >= _len) return res;
if (k == 2)
{
int i = index, j = _len - 1;
while (i < j)
{
// Find a pair
if (target - nums[i] == nums[j])
{
res.Add(new List<int> { nums[i], target - nums[i] });
// Skip duplication
while (i < j && nums[i] == nums[i + 1]) i++;
while (i < j && nums[j - 1] == nums[j]) j--;
i++;
j--;
}
// Move left bound
else if (target - nums[i] > nums[j]) i++;
// Move right bound
else j--;
}
}
else
{
for (var i = index; i < _len - k + 1; i++)
{
// Use current number to reduce K Sum into K-1 Sum
var temp = KSum(nums, target - nums[i], k - 1, i + 1);
if (temp.Any())
{
// Add previous results
foreach (var t in temp)
{
t.Add(nums[i]);
}
res.AddRange(temp);
}
// Skip duplicated numbers
while (i < _len - 1 && nums[i] == nums[i + 1]) i++;
}
}
return res;
}
}