题目描述:
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
整体思路利用C++#include<algorithm>的sort函数对vector类型的数组进行排序,然后定义三个指针i,j,k。遍历i,将问题转化为在i之后的数组中寻找nums[j]+nums[k]=-nums[i]的问题,此时将三数之和问题转变为二数之和。需要排除边界情况。
算法流程:
特判,对于数组长度 n,如果数组为空 或者数组长度小于 3,返回 空数组。
对数组进行排序。
遍历排序后数组:
若 nums[i]>0:因为已经排序好,所以后面不可能有三个数加和等于 0,直接返回结果。
对于重复元素:跳过,避免出现重复解
令左指针 L=i+1右指针 R=n−1,当 L<R 时,执行循环:
当 nums[i]+nums[L]+nums[R]==0执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 L,R 移到下一位置,寻找新的解
若和大于 0,说明 nums[R] 太大,R 左移
若和小于 0,说明 nums[L] 太小,L 右移
class Solution
{
public:
vector<vector<int>> threeSum(vector<int>& nums)
{
//vector<int>res;
vector<vector<int>> res_final;//定义存放最终结果的vector数组
sort(nums.begin(),nums.end());//利用c++#include<algorithm>库的sort函数对数组进行排序
//特殊情况
if(nums.size()<3||nums[0]>0||nums[nums.size()-1]<0)
return res_final;
for(size_t i=0;i<nums.size();i++)
{
if(nums[i]>0)
return res_final ;
if(i>0&&nums[i]==nums[i-1])
continue;//判断左界和右界是否和下一位置重复,去除重复解
int target=0-nums[i];// 将问题转化为在i之后的数组中寻找nums[j]+nums[k]=-nums[i]的问题
int k=i+1;//左指针从第二个元素开始
int m=nums.size()-1;
//排除特殊情况开始循环
while(k<m)
{
if(nums[k]>target)
break;
if((k>i+1 &&nums[k]==nums[k-1]) || nums[k]+nums[m]<target)
{
k++;
}
else if((m<nums.size()-1 && nums[m]==nums[m+1]) || nums[k]+nums[m]>target)
{
m--;
}
else
{
vector<int>res;
res.push_back(nums[i]);
res.push_back(nums[k]);
res.push_back(nums[m]);
res_final.push_back(res);
k++;
}
}
}
return res_final;
}
};