1、问题描述
给定一个整数数组,返回所有三数之和等于0的下标组合,不能重复
2、问题思路及解法
首先对原数组进行排序,只要单调才能使用双指针算法。
然后一共有i j k 三个指针,其实三数之和涉及去重问题,本代码巧妙去重
并结合了试探法,且代码思路可以扩展到四数之和、五数之和
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
//双指针算法 虽然是双指针算法,但是实际复杂度是o(n^2)的 其实是维护三个指针 i j k
vector<vector<int>> res;
sort(nums.begin(),nums.end()); //先对原数组排序,使数组有序,才能使用双指针算法
for(int i=0;i<nums.size();i++)
{
if(i&&nums[i]==nums[i-1]) continue; //排除 1 1 1 1 1 1 -2 这种情况 不含重复的三元组,所以要对指针进行判重
for(int j=i+1,k=nums.size()-1;j<k;j++)
{
if(j>i+1&&nums[j]==nums[j-1]) continue; //同理
while(j<k-1&&nums[i]+nums[j]+nums[k-1]>=0) //试探法,如果k的下一个数(k的左边的数)满足就用下一个数。注意要>=0
{
k--; //双指针算法的关键 这种试探法可以少考虑边界问题
}
if(nums[i]+nums[j]+nums[k]==0) res.push_back({nums[i],nums[j],nums[k]});
}
}
return res;
}
};
3、问题扩展
问题扩展——四数之和
class Solution {
public:
//跟三数之和相似,要进行相应改变
vector<vector<int>> fourSum(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());
vector<vector<int>> res;
for(int i=0;i<nums.size();i++)
{
if(i&&nums[i]==nums[i-1]) continue;
for(int j=i+1;j<nums.size();j++)
{
if(j>i+1&&nums[j]==nums[j-1]) continue;
for(int k=j+1,u=nums.size()-1;k<u;k++)
{
if(k>j+1&&nums[k]==nums[k-1]) continue;
while(k<u-1&&(long long)nums[i]+nums[j]+nums[k]+nums[u-1]>=target) u--; //要改成longlong类型才能过
if((long long)nums[i]+nums[j]+nums[k]+nums[u]==target)
{
res.push_back({nums[i],nums[j],nums[k],nums[u]});
}
}
}
}
return res;
}
};