15_三数之和

难度:中等

题目

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

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

示例

示例一:

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

示例二:

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

示例三:

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

提示

  • 0 <= nums.length <= 3000
  • -10^5 <= nums[i] <= 10^5

解题

题目最关键的就是如何去除重复的三元组,可以通过排序的方法解决这个问题,将数组排序后,如果遇到重复的元素,跳过即可。

  1. 首先对数组进行排序

    1
    2
    3
    int len = nums.length;
    if (nums==null|| len<3) return ans;
    Arrays.sort(nums); // 排序
  2. 固定一个数 nums[i], 定义左右指针分别指向 nums[i] 之后的两端,分别为 nums[L]nums[R], 判断和是否为 0

    int L = i + 1; int R = len - 1;

  3. 如果 nums[i] 大于 0 ,说明它和它后面的元素全部大于 0,肯定不符合条件,结束循环

  4. 如果 nums[i] = nums[i-1],说明该数字重复,应该跳过

  5. 当和为 0 时,如果 nums[L] = nums[L++], 说明该数字重复,应该 L++

  6. 当和为 0 时,如果 nums[R] = nums[R--], 说明该数字重复,应该R–

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
public List<List<Integer>> threeSum(int[] nums){
List<List<Integer>> ans = new ArrayList<>();
int len = nums.length;
if (nums==null|| len<3) return ans;
Arrays.sort(nums); // 排序
for (int i = 0; i < len; i++) {
if (nums[i]>0) break; // 如果当前数字大于0,则和一定大于0,结束循环
if (i>0 && nums[i] == nums[i-1]) continue;
int L = i+1;
int R = len-1;
while (L<R){
int sum = nums[i] + nums[L] + nums[R];
if (sum == 0){
ans.add(Arrays.asList(nums[i],nums[L],nums[R]));
while (L<R && nums[L] == nums[L+1]) L++;
while (L<R && nums[R] == nums[R-1]) R--;
L++;
R--;
}
else if (sum<0) L++; // 增大sum
else if (sum>0) R--; // 减小sum
}
}
return ans;
}