LeetCode 筆記 - 15. 3Sum

題目在此 15. 3Sum

給定一個數列,請找出 3 個數字相加等於 0 的組合

解題思維

這題如果單純暴力解,只會寫出 O(N3) 的演算法
但在這裡我們不做那種事

首先我們可以把問題降維思考為,選一個數字然後做 Two Sum
也就是說只要做 n 次 Two Sum 就可以掃瞄完畢了

所以關鍵在於說如何有效率的做 Two Sum
在這裡有兩種演算法,兩種在 Two Sum 都可以拿到好成績
但在這題因為會重複的一直做,而有明顯的差別

  1. 使用 Map 加速搜尋
    缺點是 Map 使用了大量的 Binary Search
  2. 使用 Two Pointers 大法
    Two Pointers 大法的前提是會需要先 Sorting,雖然一開始使用了 Sorting 會消耗 O(n log n)
    Sorting 過後有一些加速技巧可以使用,所以在這題的測資上,效果反而比較好

所以在實作上,筆者用了 Two Pointers 大法,來實作 Two Sum
再加上一些加速的小技巧,來跳過重複的組合

程式碼

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
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
if (length := len(nums)) < 3:
return []

nums.sort()
result = []
i = 0
while i < length - 2:
while i > 0 and i < length - 2 and nums[i] == nums[i - 1]:
i += 1

left = i + 1
right = length - 1

while left < right:
value = nums[i] + nums[left] + nums[right]
if value == 0:
result.append([nums[i], nums[left], nums[right]])

left += 1
while left < right and nums[left] == nums[left - 1]:
left += 1

right -= 1
while left < right and nums[right] == nums[right + 1]:
right -= 1

elif value < 0:
left += 1
else:
right -= 1

i += 1
return result