- 题意:给定n个数,让我们在其中选择3个或者是4个,使其的和等于一个target,找出所有的存在的解法,并没有重复。
- 本质上是对2sum的扩展,我们在面对2Sum问题的时候,首先对数组nums进行一个排序,然后维护两个指针,一个从小到大,一个从大到小的遍历整个数组,直到这两个指针相遇。
- r=0, l=nums.size()
- 当r<l的时候
- 如果nums[r] + nums[l] < target: r+=1
- 如果nums[r] + nums[l] > target: l -= 1
- 如果两个相等,则我们找到一组解{nums[l], nums[r]},然后我们再依次遍历,直到找到不同的l和r,避免出现重复的解。
- 2Sum问题的解法如上所示,那么对于我们的N Sum问题,我们可以使用递归的方法来逐渐将N Sum问题转化为2Sum问题。
1、定义nums, N, target, new_list{维护现有的list}
2、如果N小于2,则转入2SUM算法求解,不同的在于如果找到解的话,解需要merge new_list
3、如果N大于2,则遍历nums
- 对于nums 中的第i个元素,我们
- new_list.append(nums[i]),
- target -= nums[i],
- nums = nums[i:]
- N -= 1
- 将更新后的这些参数传递到第2步骤,进行递归。
- 注意⚠️,为了避免重复,如果nums[i] == nums[i-1],我们则跳过当前的i。
- 注意,这里不能是nums[i] == nums[i+1],则跳过i,因为删除nums里面原有元素的重复性。
- 恢复parameter,继续循环
- 具体实现的Code:
vector<vector<int>> find_result(vector<int> nums, int target, vector<vector<int>>& res, vector<int> newLists, int n){
// 代表从nums里面挑出来n个数的和等于target
if(n < 2){
return res;
}
if(n == 2){
int front = 0;
int end = nums.size()-1;
while(front < end){
if((nums[front] + nums[end]) < target){
front += 1;
}else{
if((nums[front] + nums[end]) > target){
end -= 1;
}else{
vector<int> solution = {nums[front], nums[end]};
solution.insert(solution.end(),newLists.begin(), newLists.end());
while(front < end && nums[front] == nums[front + 1]){
front += 1;
}
while(front < end && nums[end] == nums[end - 1]){
end -= 1;
}
res.push_back(solution);
front += 1;
end -= 1;
}
}
}
}else{
for(int i=0;i<nums.size();i++){
if(i == 0 || nums[i] != nums[i-1]){
//if(i == nums.size() - 1 || nums[i] != nums[i+1]){
newLists.push_back(nums[i]);
// vector<int> new_nums = vector<int>(nums.begin() + i + 1, nums.end());
find_result(vector<int>(nums.begin() + i + 1, nums.end()), target - nums[i], res, newLists, n-1);
newLists.pop_back();
}
}
}
return res;
}
vector<vector<int>> fourSum(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
vector<vector<int>> res = vector<vector<int>>();
// for(int i=0;i<nums.size();i++){
// for(int j=i+1;j<nums.size();j++){
// int front = j + 1;
// int end = nums.size() - 1;
// while(front < end){
// if((nums[i] + nums[j] + nums[front] + nums[end]) < target){
// front += 1;
// } else{
// if((nums[i] + nums[j] + nums[front] + nums[end]) > target){
// end -= 1;
// }else{
// vector<int> solution = {nums[i], nums[j], nums[front], nums[end]};
// res.push_back(solution);
// while(front < end && nums[front] == nums[front + 1]){
// front += 1;
// }
// while(front < end && nums[end] == nums[end - 1]){
// end -= 1;
// }
// front += 1;
// end -= 1;
// }
// }
// }
// while(j < nums.size() - 1 && nums[j] == nums[j+1]){
// j++;
// }
// }
// while(i < nums.size() - 1 && nums[i] == nums[i+1]){
// i++;
// }
// }
// return res;
return find_result(nums, target, res, vector<int>(), 4);
}