Skip to content

Commit 87be8a0

Browse files
committed
feat: add solutions to lc problem: No.0015
No.0015.3Sum
1 parent 093ec3b commit 87be8a0

File tree

9 files changed

+342
-252
lines changed

9 files changed

+342
-252
lines changed

Diff for: solution/0000-0099/0015.3Sum/README.md

+128-96
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,25 @@ nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
6060

6161
**方法一:排序 + 双指针**
6262

63-
题目不要求我们按照顺序返回三元组,因此我们可以先对数组进行排序,这样就可以方便地跳过重复的元素。
63+
我们注意到,题目不要求我们按照顺序返回三元组,因此我们不妨先对数组进行排序,这样就可以方便地跳过重复的元素。
6464

65-
接着枚举数组中的第一个元素 $nums[i]$,我们可以使用双指针的方法枚举第二个元素 $nums[j]$ 和第三个元素 $nums[k]$,使得它们的和为 $-nums[i]$。在枚举的过程中,我们需要跳过重复的元素,以避免出现重复的三元组。
65+
接下来,我们枚举三元组的第一个元素 $nums[i]$,其中 $0 \leq i \lt n - 2$。对于每个 $i$,我们可以通过维护两个指针 $j = i + 1$ 和 $k = n - 1$,从而找到满足 $nums[i] + nums[j] + nums[k] = 0$ 的 $j$ 和 $k$。在枚举的过程中,我们需要跳过重复的元素,以避免出现重复的三元组。
6666

67-
时间复杂度 $O(n^2 + n\times \log n)$。其中 $n$ 是数组的长度。枚举第一个元素需要 $O(n)$ 的时间,枚举第二个元素和第三个元素需要 $O(n)$ 的时间,排序的时间复杂度为 $O(n\times \log n)$。
67+
具体判断逻辑如下:
68+
69+
如果 $i \gt 0$ 并且 $nums[i] = nums[i - 1]$,则说明当前枚举的元素与上一个元素相同,我们可以直接跳过,因为不会产生新的结果。
70+
71+
如果 $nums[i] \gt 0$,则说明当前枚举的元素大于 $0$,则三数之和必然无法等于 $0$,结束枚举。
72+
73+
否则,我们令左指针 $j = i + 1$,右指针 $k = n - 1$,当 $j \lt k$ 时,执行循环,计算三数之和 $x = nums[i] + nums[j] + nums[k]$,并与 $0$ 比较:
74+
75+
- 如果 $x \lt 0$,则说明 $nums[j]$ 太小,我们需要将 $j$ 右移一位。
76+
- 如果 $x \gt 0$,则说明 $nums[k]$ 太大,我们需要将 $k$ 左移一位。
77+
- 否则,说明我们找到了一个合法的三元组,将其加入答案,并将 $j$ 右移一位,将 $k$ 左移一位,同时跳过所有重复的元素,继续寻找下一个合法的三元组。
78+
79+
枚举结束后,我们即可得到三元组的答案。
80+
81+
时间复杂度 $O(n^2)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组的长度。
6882

6983
<!-- tabs:start -->
7084

@@ -85,17 +99,18 @@ class Solution:
8599
continue
86100
j, k = i + 1, n - 1
87101
while j < k:
88-
if nums[i] + nums[j] + nums[k] == 0:
102+
x = nums[i] + nums[j] + nums[k]
103+
if x < 0:
104+
j += 1
105+
elif x > 0:
106+
k -= 1
107+
else:
89108
ans.append([nums[i], nums[j], nums[k]])
90109
j, k = j + 1, k - 1
91-
while j < n and nums[j] == nums[j - 1]:
110+
while j < k and nums[j] == nums[j - 1]:
92111
j += 1
93-
while k > j and nums[k] == nums[k + 1]:
112+
while j < k and nums[k] == nums[k + 1]:
94113
k -= 1
95-
elif nums[i] + nums[j] + nums[k] < 0:
96-
j += 1
97-
else:
98-
k -= 1
99114
return ans
100115
```
101116

@@ -115,18 +130,19 @@ class Solution {
115130
}
116131
int j = i + 1, k = n - 1;
117132
while (j < k) {
118-
if (nums[i] + nums[j] + nums[k] == 0) {
119-
ans.add(Arrays.asList(nums[i], nums[j++], nums[k--]));
120-
while (j < n && nums[j] == nums[j - 1]) {
133+
int x = nums[i] + nums[j] + nums[k];
134+
if (x < 0) {
135+
++j;
136+
} else if (x > 0) {
137+
--k;
138+
} else {
139+
ans.add(List.of(nums[i], nums[j++], nums[k--]));
140+
while (j < k && nums[j] == nums[j - 1]) {
121141
++j;
122142
}
123-
while (k > j && nums[k] == nums[k + 1]) {
143+
while (j < k && nums[k] == nums[k + 1]) {
124144
--k;
125145
}
126-
} else if (nums[i] + nums[j] + nums[k] < 0) {
127-
++j;
128-
} else {
129-
--k;
130146
}
131147
}
132148
}
@@ -142,20 +158,27 @@ class Solution {
142158
public:
143159
vector<vector<int>> threeSum(vector<int>& nums) {
144160
sort(nums.begin(), nums.end());
145-
int n = nums.size();
146161
vector<vector<int>> ans;
162+
int n = nums.size();
147163
for (int i = 0; i < n - 2 && nums[i] <= 0; ++i) {
148-
if (i && nums[i] == nums[i - 1]) continue;
164+
if (i && nums[i] == nums[i - 1]) {
165+
continue;
166+
}
149167
int j = i + 1, k = n - 1;
150168
while (j < k) {
151-
if (nums[i] + nums[j] + nums[k] == 0) {
152-
ans.push_back({nums[i], nums[j++], nums[k--]});
153-
while (j < k && nums[j] == nums[j - 1]) ++j;
154-
while (j < k && nums[k] == nums[k + 1]) --k;
155-
} else if (nums[i] + nums[j] + nums[k] < 0) {
169+
int x = nums[i] + nums[j] + nums[k];
170+
if (x < 0) {
156171
++j;
157-
} else {
172+
} else if (x > 0) {
158173
--k;
174+
} else {
175+
ans.push_back({nums[i], nums[j++], nums[k--]});
176+
while (j < k && nums[j] == nums[j - 1]) {
177+
++j;
178+
}
179+
while (j < k && nums[k] == nums[k + 1]) {
180+
--k;
181+
}
159182
}
160183
}
161184
}
@@ -168,31 +191,66 @@ public:
168191
169192
```go
170193
func threeSum(nums []int) (ans [][]int) {
171-
sort.Ints(nums)
172-
n := len(nums)
173-
for i := 0; i < n - 2 && nums[i] <= 0; i++ {
174-
if i > 0 && nums[i] == nums[i - 1] {
175-
continue
194+
sort.Ints(nums)
195+
n := len(nums)
196+
for i := 0; i < n-2 && nums[i] <= 0; i++ {
197+
if i > 0 && nums[i] == nums[i-1] {
198+
continue
199+
}
200+
j, k := i+1, n-1
201+
for j < k {
202+
x := nums[i] + nums[j] + nums[k]
203+
if x < 0 {
204+
j++
205+
} else if x > 0 {
206+
k--
207+
} else {
208+
ans = append(ans, []int{nums[i], nums[j], nums[k]})
209+
j, k = j+1, k-1
210+
for j < k && nums[j] == nums[j-1] {
211+
j++
212+
}
213+
for j < k && nums[k] == nums[k+1] {
214+
k--
215+
}
216+
}
217+
}
218+
}
219+
return
220+
}
221+
```
222+
223+
### **TypeScript**
224+
225+
```ts
226+
function threeSum(nums: number[]): number[][] {
227+
nums.sort((a, b) => a - b);
228+
const ans: number[][] = [];
229+
const n = nums.length;
230+
for (let i = 0; i < n - 2 && nums[i] <= 0; i++) {
231+
if (i > 0 && nums[i] == nums[i - 1]) {
232+
continue;
176233
}
177-
j, k := i + 1, n - 1
178-
for j < k {
179-
if nums[i] + nums[j] + nums[k] == 0 {
180-
ans = append(ans, []int{nums[i], nums[j], nums[k]})
181-
j, k = j + 1, k - 1
182-
for j < k && nums[j] == nums[j - 1] {
183-
j++
234+
let j = i + 1;
235+
let k = n - 1;
236+
while (j < k) {
237+
const x = nums[i] + nums[j] + nums[k];
238+
if (x < 0) {
239+
++j;
240+
} else if (x > 0) {
241+
--k;
242+
} else {
243+
ans.push([nums[i], nums[j++], nums[k--]]);
244+
while (j < k && nums[j] == nums[j - 1]) {
245+
++j;
184246
}
185-
for j < k && nums[k] == nums[k + 1] {
186-
k--
247+
while (j < k && nums[k] == nums[k + 1]) {
248+
--k;
187249
}
188-
} else if nums[i] + nums[j] + nums[k] < 0 {
189-
j++
190-
} else {
191-
k--
192250
}
193251
}
194252
}
195-
return
253+
return ans;
196254
}
197255
```
198256

@@ -205,25 +263,32 @@ func threeSum(nums []int) (ans [][]int) {
205263
*/
206264
var threeSum = function (nums) {
207265
const n = nums.length;
208-
let res = [];
209266
nums.sort((a, b) => a - b);
267+
const ans = [];
210268
for (let i = 0; i < n - 2 && nums[i] <= 0; ++i) {
211-
if (i > 0 && nums[i] == nums[i - 1]) continue;
269+
if (i > 0 && nums[i] === nums[i - 1]) {
270+
continue;
271+
}
212272
let j = i + 1;
213273
let k = n - 1;
214274
while (j < k) {
215-
if (nums[i] + nums[j] + nums[k] === 0) {
216-
res.push([nums[i], nums[j++], nums[k--]]);
217-
while (nums[j] === nums[j - 1]) ++j;
218-
while (nums[k] === nums[k + 1]) --k;
219-
} else if (nums[i] + nums[j] + nums[k] < 0) {
275+
const x = nums[i] + nums[j] + nums[k];
276+
if (x < 0) {
220277
++j;
221-
} else {
278+
} else if (x > 0) {
222279
--k;
280+
} else {
281+
ans.push([nums[i], nums[j++], nums[k--]]);
282+
while (j < k && nums[j] === nums[j - 1]) {
283+
++j;
284+
}
285+
while (j < k && nums[k] === nums[k + 1]) {
286+
--k;
287+
}
223288
}
224289
}
225290
}
226-
return res;
291+
return ans;
227292
};
228293
```
229294

@@ -241,18 +306,19 @@ public class Solution {
241306
}
242307
int j = i + 1, k = n - 1;
243308
while (j < k) {
244-
if (nums[i] + nums[j] + nums[k] == 0) {
245-
ans.Add(new List<int> { nums[i], nums[j++], nums[k--] });
246-
while (j < n && nums[j] == nums[j - 1]) {
309+
int x = nums[i] + nums[j] + nums[k];
310+
if (x < 0) {
311+
++j;
312+
} else if (x > 0) {
313+
--k;
314+
} else {
315+
ans.Add(new List<int> { nums[i], nums[j--], nums[k--] });
316+
while (j < k && nums[j] == nums[j + 1]) {
247317
++j;
248318
}
249-
while (k > j && nums[k] == nums[k + 1]) {
319+
while (j < k && nums[k] == nums[k + 1]) {
250320
--k;
251321
}
252-
} else if (nums[i] + nums[j] + nums[k] < 0) {
253-
++j;
254-
} else {
255-
--k;
256322
}
257323
}
258324
}
@@ -294,40 +360,6 @@ def three_sum(nums)
294360
end
295361
```
296362

297-
### **TypeScript**
298-
299-
```ts
300-
function threeSum(nums: number[]): number[][] {
301-
nums.sort((a, b) => a - b);
302-
const ans = [];
303-
const n = nums.length;
304-
for (let i = 0; i < n - 2 && nums[i] <= 0; i++) {
305-
const target = 0 - nums[i];
306-
let l = i + 1;
307-
let r = n - 1;
308-
while (l < r) {
309-
if (nums[l] + nums[r] === target) {
310-
ans.push([nums[i], nums[l++], nums[r--]]);
311-
while (nums[l] === nums[l - 1]) {
312-
l++;
313-
}
314-
while (nums[r] === nums[r + 1]) {
315-
r--;
316-
}
317-
} else if (nums[l] + nums[r] < target) {
318-
l++;
319-
} else {
320-
r--;
321-
}
322-
}
323-
while (nums[i] === nums[i + 1]) {
324-
i++;
325-
}
326-
}
327-
return ans;
328-
}
329-
```
330-
331363
### **Rust**
332364

333365
```rust

0 commit comments

Comments
 (0)