三数之和

算法-三数之和

背景

  • 算法–三数之和

  • 博主以代码随想录算法公开课进行学习

题目

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

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

    示例:

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

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

思路

  • 哈希法:俩层for循环,再用哈希法确定第3个数,但是去重难度大
  • 双指针法:先将数组排序,一层for循环,i重下标为0开始,建立left指针指向i的下一位、rigth指针指向最后一位
  • nums[i] + nums[left] + nums[right] > 0表示大了,right向左移
  • nums[i] + nums[left] + nums[right] < 0表示小了,left向右移
  • nums[i] + nums[left] + nums[right] = 0表示找到符合标准的

代码

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
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
//排序,为去重准备
Arrays.sort(nums);
for(int i = 0;i < nums.length; i++){
if(nums[i] > 0){
return result; //首位最小但是大于0,表示没有负数,直接返回结果
}
if(i > 0 && nums[i] == nums[i-1]){ //去重,
continue;
}
int left = i + 1; //左指针
int rigth = nums.length - 1; //右指针
while(rigth > left){ //没有=,因为要求3位数,等于只剩2位
int sum = nums[i] + nums[left] +nums[rigth];
if(sum > 0){ //和大,右指针往左移动
rigth--;
}else if(sum < 0){ //和小,左指针往右移动
left++;
}else{
result.add(Arrays.asList(nums[i],nums[left],nums[rigth])); //找到符合的结果
while(rigth > left && nums[rigth] == nums[rigth-1]){ //去重
rigth--;
}
while(rigth > left && nums[left] == nums[left+1]){ //去重
left++;
}

rigth--;
left++;
}
}
}
return result;
}
}

总结

  • 三数之和的核心逻辑是:排序 + 固定第一个数 + 双指针找后两个数,去重逻辑是避免重复三元组的关键。