欢迎来到我的小小世界

Change is a million times less painful than regret

0%

LC15.三数之和

题目地址(3sum/“>15. 三数之和)

https://leetcode-cn.com/problems/3sum/

题目描述

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
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

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

 

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]


示例 2:

输入:nums = []
输出:[]


示例 3:

输入:nums = [0]
输出:[]


 

提示:

0 <= nums.length <= 3000
-105 <= nums[i] <= 105

前置知识

  • 双指针、两数之和

公司

  • 字节跳动、Facebook、微软、苹果

思路

这题的思路是建立在两数之和的基础进行求解的,与两数之和不同的是,这里不再要求返回索引,,因此先进行排序,,然后使用双指针的思路是颗星的。具体的算法是对原数组进行依次排序,然后一层循环固定一个元素,循环内部利用双指针找出剩下的两个元素,这里特别注意需要去重。上述算法出去排序部分的时间复杂度为O(n^2),相比之下排序过程不会成为性能瓶颈。

关键点

  • 这里的关键点除了基本的算法思想之外,注意list的定义是每次循环的时候定义的(翻译的python代码就是这样定义得)虽然这样定义会导致空间的浪费,但是鉴于题目要求的特殊性,如果不是每次循环定义,而是使用同一个list会导致越来越多,最后全部集中在一个list中。

代码

  • 语言支持:Java

Java Code:

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

class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int n=nums.length;
Arrays.sort(nums);
List<List<Integer>> res=new ArrayList();

//要找到三个数,因此需要找到倒数n-3个数即可
for(int i=0;i<nums.length-2;i++){
if(i>0&&nums[i]==nums[i-1]) continue;
//固定i,寻找l和r
int l=i+1;
int r=n-1;
while(l<r){
if(nums[i]+nums[l]+nums[r]<0) l+=1;
else if(nums[i]+nums[l]+nums[r]>0) r-=1;
else{
List<Integer> tmp=new ArrayList();
tmp.add(nums[i]);
tmp.add(nums[l]);
tmp.add(nums[r]);
res.add(tmp);
//去重操作
while(l<r && nums[l]==nums[l+1])
{l+=1;}//这样写不会越界
while(l<r && nums[r]==nums[r-1])
{r-=1;}
l+=1;
r-=1;
}

}
}
return res;
}

}

复杂度分析

令 n 为数组长度。

  • 时间复杂度:$O(n^2)$
  • 空间复杂度:$O(n)$
-------- 本文结束 感谢阅读 --------