Tino又想吃肉了

三数之和

Word count: 631Reading time: 2 min
2021/09/03

两数之和的进阶版,很容易想到使用多个指针,可以将三数之和转化为两数之和问题,但是这个问题的规模使得写的时候由于超时快被气死…
系统复习系列

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
0 <= nums.length <= 3000
-105 <= nums[i] <= 105

很显然,为了a + b + c = 0,我们可以转化成a + b = -c,即双指针的两数之和问题,当然我们也可以直接使用三个指针,本质上并无区别…
但这题关键的地方在于优化算法速度,不然随随便便就超时.
思路仍然是先排序,然后确定a的大小,将a从0遍历至length-1,在每轮遍历再通过b和c指针找出符合题意的答案。
以下为实现代码

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
class Solution {
func threeSum(_ nums: [Int]) -> [[Int]] {
if nums.count < 3 {
return []
}
var res = [[Int]]()
// 排序
var arr = nums.sorted(by:{
return $0 < $1
})

// 将a从0遍历至末尾
for a in 0..<arr.count {
// 如果a大于0并且与前一个数相同,则跳过本轮循环
if (a > 0 && arr[a] == arr[a - 1])
{
continue
}
var b = a + 1
var c = arr.count - 1
while (b < c) {
// 如果b与前面一轮循环的b相同,也跳过本轮循环。
// b要大于a+1是因为a+1是第一个b值
while (b > a + 1 && b < arr.count && arr[b] == arr[b - 1]) {
b += 1
}
// 如果b大于或等于c,说明本轮循环已没有不重复的组了 跳出循环
if b >= c {
break
}
let cnt = arr[a] + arr[b] + arr[c]
if cnt == 0 {
let temp = [arr[a],arr[b],arr[c]]
// 由于确定了a和b不同,即c肯定不同,所以不用判断res中是否已有temp
res.append(temp)
b += 1
} else if cnt < 0 {
b += 1
} else if cnt > 0 {
c -= 1
}
}
}
return res
}
}

总结

本题虽然是两数之和同类型的题,但是需要注意的细节比两数之和多了很多,可以锻炼到对双指针的灵活运用,同时也涉及到了一些算法优化。

CATALOG
  1. 1. 总结