【leetcode】18 4 sum
题目描述
https://leetcode-cn.com/problems/4sum/description/
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
解法1
本题是3sum的升级版,基本思路也与3sum差不多,首先对数组进行从小到大的排序,方便去重以及查找。
然后对于前两个元素进行循环遍历,后两个元素则使用对撞指针的方法,从两个边界向内查找和等于target - a - b的结果。
时间复杂度:O(n^3)
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 ++)
{
for (int j = i + 1; j < nums.size() - 2; j ++)
{
int sum = target - nums[i] - nums[j];
/*
* 对撞指针
*/
int l = j + 1;//左边界
int r = nums.size() - 1;//右边界
while (l < r)
{
if (nums[l] + nums[r] == sum){//满足条件
res.push_back({nums[i],nums[j],nums[l++],nums[r--]});
while(l < r && nums[r] == nums[r + 1])//右值去重
r --;
while(l < r && nums[l] == nums[l - 1])//左值去重
l ++;
}else if (nums[l] + nums[r] > sum)//和大于sum,则右边界向左移动
{
r --;
}else{//和小于sum,则左边界向右移动
l ++;
}
}
while(j < nums.size() - 2 && nums[j + 1] == nums[j])//去重
j ++;
}
while(i < nums.size() - 3 && nums[i + 1] == nums[i])//去重
i ++;
}
return res;
}
在以上的基础上,可以对一些特殊情况添加判断以减少无效的循环遍历:
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 ++)
{
/*
* 若当前值与最后三个最大值和仍小于target,则本轮不需要继续遍历了
*/
if(nums[i] + nums[nums.size() - 1] + nums[nums.size() - 2] + nums[nums.size() - 3] < target)
continue;
/*
* 若前四个最小值之和已经大于target了,则以后就不可能继续更小了,不需要继续遍历了
*/
if(nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target)
return res;
for (int j = i + 1; j < nums.size() - 2; j ++)
{
/*
* 若前两个值与最后两个最大值的和仍小于target,则本轮不需要继续遍历了
*/
if(nums[i] + nums[j] + nums[nums.size() - 1] + nums[nums.size() - 2] < target)
continue;
/*
* 若第一个值与第二层本轮循环前三个最小值之和已经大于target了,
* 则本轮循环以后就不可能继续更小了,则本轮循环不需要继续遍历了
*/
if(nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target)
break;
int sum = target - nums[i] - nums[j];
int l = j + 1;
int r = nums.size() - 1;
while (l < r)
{
if (nums[l] + nums[r] == sum){
res.push_back({nums[i],nums[j],nums[l++],nums[r--]});
while(l < r && nums[r] == nums[r + 1])
r --;
while(l < r && nums[l] == nums[l - 1])
l ++;
}else if (nums[l] + nums[r] > sum)
{
r --;
}else{
l ++;
}
}
while(j < nums.size() - 2 && nums[j + 1] == nums[j])
j ++;
}
while(i < nums.size() - 3 && nums[i + 1] == nums[i])
i ++;
}
return res;
}