@@ -60,11 +60,25 @@ nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
60
60
61
61
** 方法一:排序 + 双指针**
62
62
63
- 题目不要求我们按照顺序返回三元组,因此我们可以先对数组进行排序 ,这样就可以方便地跳过重复的元素。
63
+ 我们注意到, 题目不要求我们按照顺序返回三元组,因此我们不妨先对数组进行排序 ,这样就可以方便地跳过重复的元素。
64
64
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 $。在枚举的过程中,我们需要跳过重复的元素,以避免出现重复的三元组。
66
66
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$ 为数组的长度。
68
82
69
83
<!-- tabs:start -->
70
84
@@ -85,17 +99,18 @@ class Solution:
85
99
continue
86
100
j, k = i + 1 , n - 1
87
101
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 :
89
108
ans.append([nums[i], nums[j], nums[k]])
90
109
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 ]:
92
111
j += 1
93
- while k > j and nums[k] == nums[k + 1 ]:
112
+ while j < k and nums[k] == nums[k + 1 ]:
94
113
k -= 1
95
- elif nums[i] + nums[j] + nums[k] < 0 :
96
- j += 1
97
- else :
98
- k -= 1
99
114
return ans
100
115
```
101
116
@@ -115,18 +130,19 @@ class Solution {
115
130
}
116
131
int j = i + 1 , k = n - 1 ;
117
132
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 ]) {
121
141
++ j;
122
142
}
123
- while (k > j && nums[k] == nums[k + 1 ]) {
143
+ while (j < k && nums[k] == nums[k + 1 ]) {
124
144
-- k;
125
145
}
126
- } else if (nums[i] + nums[j] + nums[k] < 0 ) {
127
- ++ j;
128
- } else {
129
- -- k;
130
146
}
131
147
}
132
148
}
@@ -142,20 +158,27 @@ class Solution {
142
158
public:
143
159
vector<vector<int >> threeSum(vector<int >& nums) {
144
160
sort(nums.begin(), nums.end());
145
- int n = nums.size();
146
161
vector<vector<int >> ans;
162
+ int n = nums.size();
147
163
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
+ }
149
167
int j = i + 1, k = n - 1;
150
168
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) {
156
171
++j;
157
- } else {
172
+ } else if (x > 0) {
158
173
--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
+ }
159
182
}
160
183
}
161
184
}
@@ -168,31 +191,66 @@ public:
168
191
169
192
```go
170
193
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 ;
176
233
}
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 ;
184
246
}
185
- for j < k && nums[k] == nums[k + 1] {
186
- k--
247
+ while ( j < k && nums [k ] == nums [k + 1 ]) {
248
+ -- k ;
187
249
}
188
- } else if nums[i] + nums[j] + nums[k] < 0 {
189
- j++
190
- } else {
191
- k--
192
250
}
193
251
}
194
252
}
195
- return
253
+ return ans ;
196
254
}
197
255
```
198
256
@@ -205,25 +263,32 @@ func threeSum(nums []int) (ans [][]int) {
205
263
*/
206
264
var threeSum = function (nums ) {
207
265
const n = nums .length ;
208
- let res = [];
209
266
nums .sort ((a , b ) => a - b);
267
+ const ans = [];
210
268
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
+ }
212
272
let j = i + 1 ;
213
273
let k = n - 1 ;
214
274
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 ) {
220
277
++ j;
221
- } else {
278
+ } else if (x > 0 ) {
222
279
-- 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
+ }
223
288
}
224
289
}
225
290
}
226
- return res ;
291
+ return ans ;
227
292
};
228
293
```
229
294
@@ -241,18 +306,19 @@ public class Solution {
241
306
}
242
307
int j = i + 1 , k = n - 1 ;
243
308
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 ]) {
247
317
++ j ;
248
318
}
249
- while (k > j && nums [k ] == nums [k + 1 ]) {
319
+ while (j < k && nums [k ] == nums [k + 1 ]) {
250
320
-- k ;
251
321
}
252
- } else if (nums [i ] + nums [j ] + nums [k ] < 0 ) {
253
- ++ j ;
254
- } else {
255
- -- k ;
256
322
}
257
323
}
258
324
}
@@ -294,40 +360,6 @@ def three_sum(nums)
294
360
end
295
361
```
296
362
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
-
331
363
### ** Rust**
332
364
333
365
``` rust
0 commit comments