题目描述
leetcode_hot100_15
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。
提示:
3 <= nums.length <= 3000
-105 <= nums[i] <= 105
错误示范
//暴力解法
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> cur_sum;
for(int i=0;i<nums.size();i++){
for(int j=i+1;j<nums.size();j++){
for(int k=j+1;k<nums.size();k++){
if(nums[i]+nums[j]+nums[k]==0){
vector<int> c_num;
if(nums[i]<=nums[j]){//从小到大排一下,去除重复的
if(nums[j]<=nums[k]){
c_num.push_back(nums[i]);
c_num.push_back(nums[j]);
c_num.push_back(nums[k]);
}else{
if(nums[k]<=nums[i]){
c_num.push_back(nums[k]);
c_num.push_back(nums[i]);
c_num.push_back(nums[j]);
}else{
c_num.push_back(nums[i]);
c_num.push_back(nums[k]);
c_num.push_back(nums[j]);
}
}
}else{
if(nums[i]<=nums[k]){
c_num.push_back(nums[j]);
c_num.push_back(nums[i]);
c_num.push_back(nums[k]);
}else{
if(nums[k]<=nums[j]){
c_num.push_back(nums[k]);
c_num.push_back(nums[j]);
c_num.push_back(nums[i]);
}else{
c_num.push_back(nums[j]);
c_num.push_back(nums[k]);
c_num.push_back(nums[i]);
}
}
}
int f=0;
for(int x=0;x<cur_sum.size() && f==0;x++){
if(c_num[0]==cur_sum[x][0] && c_num[1]==cur_sum[x][1] && c_num[2]==cur_sum[x][2]){
f=1;
}
}
if(f==0){
cur_sum.push_back(c_num);
}
}
}
}
}
return cur_sum;
}
};
正解
思路:双指针
先从小到达排序,固定一个数nums[i]后,左指针指向他后面的数,右指针指向最后一个数,看三者之和是否为0
1.和为0:左指针右移到和左指针当前指向的数一致的为止,右指针左移到和右指针当前指向的数一致为止。(移动过程中左指针必须要保持在右指针左边)
2.和大于0:右指针左移
3.和小于0:左指针右移
注意:遍历到nums[i+1](即下一个数)时,要跳过与前一个数一致的,因为结果一样的只输出一次。
遍历到nums[i]>0(或nums数组结束)时就停下,因为升序排列后面三个正整数和不可能为0.
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> cur_sum;
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size() && nums[i]<=0;i++){
if(i==0 || nums[i]!=nums[i-1]){//注意i=0要特殊处理,否则越界
int l=i+1;
int r=nums.size()-1;
while(l<r){
if(nums[i]+nums[l]+nums[r]==0){
vector<int> c_num;
c_num.push_back(nums[i]);
c_num.push_back(nums[l]);
c_num.push_back(nums[r]);
cur_sum.push_back(c_num);
while(l<r && nums[l]==nums[l+1]){//必须有l<r,否则越界
l++;
}
while(r>l && nums[r]==nums[r-1]){
r--;
}
l++;
r--;
}else if(nums[i]+nums[l]+nums[r]>0){
r--;
}else{
l++;
}
}
}
}
return cur_sum;
}
};