Leetcode-15.三数之和

题目描述

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

解法1:双指针法

1.排序,先将nums排序

2.固定3个指针中最左(小)数字指针k,双指针i,j分别在数组索引[k+1,nums.length()-1]两端,通过双指针交替向中间移动,记录对于固定指针k的所有满足nums[k]+nums[i]+nums[j]=0的i,j组合:

  1. 当nums[k]>0时直接跳出:因为nums[j]>=nums[i]>=nums[k]>0,3数之和必然不可能为0,在k之后也不可能再找到结果了。
  2. 当k>0且nums[k]==nums[k-1]时即跳过此元素nums[k]:因为已经将nums[k-1]的所有组合加入到结果中。
  3. 当i<j时循环计算s=nums[k]+nums[i]+nums[j],并按照下列规则进行移动:
    • 当s<0时,i+=1并跳过所有重复的nums[i],
    • 当s>0时,j-=1并跳过所有重复的nums[j],
    • 当s==0时,记录组合[k,i,j]至res,并执行i+=1,j-=1并跳过所有重复的nums[i]和nums[j],防止记录重复组合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
int i,j;
int k=0;
int s;

if(nums.size()<=2)
return res;
sort(nums.begin(),nums.end());
i=0;j=nums.size()-1;
if(nums[i]>0||nums[j]<0)
return res;
for(;k<nums.size()-2;k++)
{
if(nums[k]>0)
break;
if(k>0&&nums[k]==nums[k-1])
continue;
i=k+1;
j=nums.size()-1;
while(i<j)
{

if(nums[j]<0)
break;
s=nums[k]+nums[i]+nums[j];
if(s==0)
{
res.push_back(vector<int>{nums[k],nums[i],nums[j]});
i++;
while(nums[i]==nums[i-1]&&i<j)
i++;
j--;
while(nums[j]==nums[j+1]&&i<j)
j--;

}
else if(s<0)
{
i++;
while(nums[i]==nums[i-1]&&i<j)
i++;
}
else
{
j--;
while(nums[j]==nums[j+1]&&i<j)
j--;
}
}
}
return res;
}
};

复杂度分析:
1):时间复杂度 O($N^2$)
2 ):其中固定指针k循环复杂度 O(N),双指针 i,j 复杂度 O(N)。
空间复杂度 O(1):指针使用常数大小的额外空间。