-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path3Sum.go
141 lines (133 loc) · 3.25 KB
/
3Sum.go
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package threesum
import (
"sort"
)
// ThreeSumBurst : 暴力解 : O(n^3)
func ThreeSumBurst(nums []int) [][]int {
result := [][]int{}
sort.Ints(nums) // O(n log n)
for i := 0; i < len(nums); i++ {
// 需要跟上一次不同
if i > 0 && nums[i] == nums[i-1] {
continue
}
for j := i + 1; j < len(nums); j++ {
// 需要跟上一次不同
if j > i+1 && nums[j] == nums[j-1] {
continue
}
for k := j + 1; k < len(nums); k++ {
if nums[i]+nums[j]+nums[k] == 0 {
result = append(result, []int{nums[i], nums[j], nums[k]})
}
}
}
}
return result
}
/*
ThreeSumDoublePoint : 最佳解, 排序 + 雙指針法 (滑動視窗) O(n^2)
1. 特判,對於數組長度 n,如果數組為 null 或者數組長度小於 3,返回 []。
2. 對數組進行排序。
3. 遍歷排序後數組:
- 對於重複元素:跳過,避免出現重複解
- 令左指針 L=i+1,右指針 R=n−1,當 L<R 時,執行循環:
- 當nums[i]+nums[L]+nums[R]==0,執行循環,判斷左界和右界是否和下一位置重複,
去除重複解。並同時將 L,R 移到下一位置,尋找新的解
- 若和大於 0,說明 nums[R] 太大,R 左移
- 若和小於 0,說明 nnums[L] 太小,L 右移
*/
func ThreeSumDoublePoint(nums []int) [][]int {
result := [][]int{}
if len(nums) < 3 {
return result
}
sort.Ints(nums) // O(n log n)
start, end, addNum := 0, 0, 0
for i := 1; i < len(nums)-1; i++ {
start, end = 0, len(nums)-1
if i > 1 && nums[i] == nums[i-1] {
// 去掉重複
start = i - 1
}
for start < i && end > i {
if start > 0 && nums[start] == nums[start-1] {
// 去掉重複
start++
continue
}
if end < (len(nums)-1) && nums[end] == nums[end+1] {
// 去掉重複
end--
continue
}
addNum = nums[start] + nums[end] + nums[i]
if addNum == 0 {
result = append(result, []int{nums[start], nums[i], nums[end]})
start++
end--
} else if addNum > 0 {
end--
} else {
start++
}
}
}
return result
}
func ThreeSumHashTable(nums []int) [][]int {
result := [][]int{}
if len(nums) < 3 {
return result
}
sort.Ints(nums) // O(n log n)
for i := 0; i < len(nums)-2; i++ {
// 避免重複的起始元素
if i > 0 && nums[i] == nums[i-1] {
continue
}
seen := make(map[int]bool)
target := -nums[i] // 目標值為當前元素的相反數
for j := i + 1; j < len(nums); j++ {
complement := target - nums[j] // 找到與當前元素配對的目標元素
if seen[complement] {
result = append(result, []int{nums[i], complement, nums[j]})
// 避免重複的配對元素
for j < len(nums)-1 && nums[j] == nums[j+1] {
j++
}
}
seen[nums[j]] = true
}
}
return result
}
func ThreeSumTwoPointer(nums []int) [][]int {
result := [][]int{}
sort.Ints(nums)
for i := 0; i < len(nums)-2; i++ {
if i > 0 && nums[i] == nums[i-1] {
continue
}
target, l, r := -nums[i], i+1, len(nums)-1
for l < r {
sum := nums[l] + nums[r]
if sum == target {
result = append(result, []int{nums[i], nums[l], nums[r]})
l++
r--
for l < r && nums[l] == nums[l-1] {
l++
}
for l < r && nums[r] == nums[r+1] {
r--
}
} else if sum > target {
r--
} else if sum < target {
l++
}
}
}
return result
}