Leetcode-015-三数之和

Leecode-015-三数之和

思路:排序+双指针

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

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

1
2
3
4
5
6
7
8
9
示例:

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

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

方法:排序+双指针

算法思路

  • 首先对排序后的数组进行遍历,固定一个nums[i] 。
  • 其次使用一个指针L指向 i + 1 的位置,一个指针R指向 nums.length - 1的位置,同时计算nums[i] + nums[L] + nums[R],计算这三个数的和是否等于0
  • 细节条件一定要注意
    • 如果nums[i] > 0 ,那么这三个数的和比不可能等于0
    • 如果nums[i] == nums[i -1] ,则说明该数字重复,会导致结果的重复,所以应该跳过
    • 当sum == 0的时候,如果nums[L] == nums[L+1],则会导致结果的重复,应该跳过,(L++)
    • 当sum == 0的时候,如果nums[R] == nums[R - 1],则会导致结果的重复,应该跳过,(R–)

举个例子:

  1. 首先进行排序

mark

  1. 第一轮循环

mark

mark

mark

mark

mark

mark

  1. 第二轮循环

mark

mark

mark

  1. 第三轮循环

mark

mark

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
class Solution {
public List<List<Integer>> threeSum(int[] nums) {

// 初始化:ans记录结果
List<List<Integer>> ans = new ArrayList<>();

// 特殊判断
if (nums == null || nums.length < 3) {
return ans;
}

// 1. 对数组进行排序
Arrays.sort(nums);


// 2. 遍历数组中的每一个数字,固定nums[i]
for (int i = 0; i < nums.length; i++) {
// 如果当前数字大于0,,则三数之和一定大于0,所以结束循环
if (nums[i] > 0) {
break;
}

// 注意:对 i 进行去重
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}

// 初始化双指针
int L = i + 1;
int R = nums.length - 1;

// 3. 指针遍历
while (L < R) {
int sum = nums[i] + nums[L] + nums[R];

// 如果三数之和等于0
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++;
} else if (sum > 0) {
R--;
}
}
}
return ans;
}
}

复杂度分析:

  • 时间复杂度:O(n^2) 排序O(nlogn) + 循环O(n^2) = O(n^2)
  • 空间复杂度:O(1) 没有使用额外的空间
打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2019-2022 Zhuuu
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信