题目描述
解法
首先我发现左右端点指针的前提一般是有序序列,所以一般跟排序一块,这类题是这样,二分查找也是这样
思路: 一个固定指针 k 遍历数组,两个动指针 i,j 分设在数组索引 (k,len(nums)) 两端,通过双指针交替向中间移动,记录对于每个固定指针 k 的所有满足题目要求 nums[k] + nums[i] + nums[j] == 0 的 i,j 组合
- 当 k > 0且nums[k] == nums[k - 1]时即跳过此元素。因为已经将 nums[k - 1] 的所有组合加入到结果中,本次双指针搜索只会得到重复组合。
- i,j 分设在数组索引 (k,len(nums)) 两端,当 i < j 时循环计算s = nums[k] + nums[i] + nums[j],并按照以下规则执行双指针移动:
1. 当s < 0时,i ++ 并跳过所有重复的nums[i];
2. 当s > 0时,j - - 并跳过所有重复的nums[j];
3. 当s == 0时,记录组合[k, i, j] 至 ans,执行 i ++ 和 j - - 并跳过所有重复的nums[i]和nums[j],防止记录到重复组合。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int> > ans;
sort(nums.begin(),nums.end());
int len = nums.size();
//限制条件:num[i]作为三者中最小值,一定不能超过0
for(int i=0;i<len&&nums[i]<=0;i++)
{
//保证和上一次枚举的元素不一样
if(i>0&&nums[i]==nums[i-1])
continue;
int start=i+1,end=len-1;
while(start<end)
{
int sum=nums[start]+nums[end]+nums[i];
if(sum==0)
{
ans.push_back({nums[start],nums[end],nums[i]});
while(start<end&&nums[start]==nums[++start]);//去重
while(start<end&&nums[end]==nums[--end]);//去重
}
else if(sum>0)
while(start<end&&nums[end]==nums[--end]);//去重
else
while(start<end&&nums[start]==nums[++start]);//去重
}
}
return ans;
}
};
类似的练习题: 【左右端点指针】LeetCode - 16. 最接近的三数之和