leetcode 18.四数之和
题目描述
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
满足要求的四元组集合为:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
解题思路
对于该题选择暴力查询的方法可以实现结果,但是时间复杂度太高。对于暴力方法的优化,选择用双指针的做法。
四数相加解题步骤
- 数组的长度是否符合要求
- 进行数组的排序,这样可以为下面条件的遍历和数字的筛选做好准备
- 选择第一个数字,并加上筛选条件,避免重复
- 选择第二个数字,加上筛选条件,避免重复
- 双子座筛选剩下的两个数字,这里左右指针移动的条件四数之和与目标值相比较,具体参考代码注释
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,用于第一个数的选择
for(int i=0; i<nums.size(); i++){
// 避免第一个数字重复的选择
if(i>0 && nums[i] == nums[i-1]){
continue;
}
// 第二个for,用于第二个数字的选择
for(int j=i+1; j<nums.size(); j++){
int l=j+1, r=nums.size()-1; // 在第一、二个数的基础上,定义指针位置
// 避免数组第二个数字的重复
if(j>i+1 && nums[j] == nums[j-1]){
continue;
}
// 双指针筛选
while(l<r){
// 满足条件做进一步的筛选
if (nums[i] + nums[j] + nums[l] + nums[r] == target){
vector<int> temp={nums[i], nums[j], nums[l], nums[r]};
l++;
// 避免第三个数字的重复
if(nums[l] == nums[l-1]){
if(l == r){ // 当两个指针相遇时,依然重复,把当前结果保存,并跳出
res.push_back(temp);
}
continue;
}
res.push_back(temp);
}
else if (nums[i] + nums[j] + nums[l] + nums[r] > target){
r--; // 排序后,数字太大,右指针减小一
}
else{
l++; // 排序后,数字太小,左指针加上一
}
}
}
}
return res;
}
};
下面分享一下回溯算法,如果数组太大,在leetcode提交超时,就当锻炼一下回溯算法解题思路了
回溯算法框架
- 递归出口
- 去选择满足目标结果的可能的条件
- 递归
- 状态重置
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> res;
vector<int> track;
sort(nums.begin(), nums.end());
backTrack(res, nums, track, target, 0);
return res;
}
void backTrack(vector<vector<int>>& res, vector<int> nums, vector<int> track, int target, int index){
if(track.size() == 4){
if(target == 0){
res.push_back(track);
}
return ;
}
for(int i=index; i<nums.size(); i++){
// 该判断是为了避免数组重复
if(i>index && nums[i] == nums[i-1]){
continue;
}
track.push_back(nums[i]);
target -= nums[i];
if(target<0 && nums[i] >=0){
return;
}
backTrack(res, nums, track, target, i+1);
target += nums[i];
track.pop_back();
}
}
};
欢迎大家关注我的个人公众号,同样的也是和该博客账号一样,专注分享技术问题,我们一起学习进步