@@ -53,19 +53,15 @@ tags:
53
53
54
54
<!-- solution:start -->
55
55
56
- ### 方法一:排序
56
+ ### 方法一:哈希表
57
57
58
- 我们先将数组排序,然后用一个变量 $t$ 记录当前连续序列的长度 ,用一个变量 $ans$ 记录最长连续序列的长度。
58
+ 我们可以用一个哈希表 $\textit{s}$ 存储数组中所有的元素 ,用一个变量 $\textit{ ans} $ 记录最长连续序列的长度,用一个哈希表 $\textit{d}$ 记录每个元素 $x$ 所在的连续序列的长度 。
59
59
60
- 接下来,我们从下标 $i=1$ 开始遍历数组,对于当前遍历到的元素 $nums [ i ] $:
60
+ 接下来,我们遍历数组中每个元素 $x$,用一个临时变量 $y$ 记录当前连续序列的最大值,初始时 $y = x$。然后,我们不断尝试匹配 $y+1, y+2, y+3, \dots$,直到匹配不到为止,过程中将匹配到的元素从哈希表 $\textit{s}$ 中移除。那么,当前元素 $x$ 所在的连续序列的长度即为 $d [ x ] = d [ y ] + y - x$,然后更新答案 $\textit{ans} = \max(\textit{ans}, d [ x ] )$。
61
61
62
- - 如果 $nums[ i] =nums[ i-1] $,则说明当前元素重复,无需考虑;
63
- - 如果 $nums[ i] =nums[ i-1] +1$,则说明当前元素可以接在上一个连续序列后面以形成更长的连续序列,我们更新 $t = t + 1$,然后更新答案 $ans = \max(ans, t)$;
64
- - 否则,说明当前元素无法接在上一个连续序列后面,我们将 $t$ 重新置为 $1$。
62
+ 遍历结束后,返回答案 $\textit{ans}$ 即可。
65
63
66
- 最终,我们返回答案 $ans$ 即可。
67
-
68
- 时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 是数组的长度。
64
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $\textit{nums}$ 的长度。
69
65
70
66
<!-- tabs:start -->
71
67
@@ -74,19 +70,16 @@ tags:
74
70
``` python
75
71
class Solution :
76
72
def longestConsecutive (self , nums : List[int ]) -> int :
77
- n = len (nums)
78
- if n < 2 :
79
- return n
80
- nums.sort()
81
- ans = t = 1
82
- for a, b in pairwise(nums):
83
- if a == b:
84
- continue
85
- if a + 1 == b:
86
- t += 1
87
- ans = max (ans, t)
88
- else :
89
- t = 1
73
+ s = set (nums)
74
+ ans = 0
75
+ d = defaultdict(int )
76
+ for x in nums:
77
+ y = x
78
+ while y in s:
79
+ s.remove(y)
80
+ y += 1
81
+ d[x] = d[y] + y - x
82
+ ans = max (ans, d[x])
90
83
return ans
91
84
```
92
85
@@ -95,21 +88,19 @@ class Solution:
95
88
``` java
96
89
class Solution {
97
90
public int longestConsecutive (int [] nums ) {
98
- int n = nums . length ;
99
- if (n < 2 ) {
100
- return n ;
91
+ Set< Integer > s = new HashSet<> () ;
92
+ for ( int x : nums ) {
93
+ s . add(x) ;
101
94
}
102
- Arrays . sort(nums);
103
- int ans = 1 , t = 1 ;
104
- for (int i = 1 ; i < n; ++ i) {
105
- if (nums[i] == nums[i - 1 ]) {
106
- continue ;
107
- }
108
- if (nums[i] == nums[i - 1 ] + 1 ) {
109
- ans = Math . max(ans, ++ t);
110
- } else {
111
- t = 1 ;
95
+ int ans = 0 ;
96
+ Map<Integer , Integer > d = new HashMap<> ();
97
+ for (int x : nums) {
98
+ int y = x;
99
+ while (s. contains(y)) {
100
+ s. remove(y++ );
112
101
}
102
+ d. put(x, d. getOrDefault(y, 0 ) + y - x);
103
+ ans = Math . max(ans, d. get(x));
113
104
}
114
105
return ans;
115
106
}
@@ -122,21 +113,16 @@ class Solution {
122
113
class Solution {
123
114
public:
124
115
int longestConsecutive(vector<int >& nums) {
125
- int n = nums.size();
126
- if (n < 2) {
127
- return n;
128
- }
129
- sort(nums.begin(), nums.end());
130
- int ans = 1, t = 1;
131
- for (int i = 1; i < n; ++i) {
132
- if (nums[ i] == nums[ i - 1] ) {
133
- continue;
134
- }
135
- if (nums[ i] == nums[ i - 1] + 1) {
136
- ans = max(ans, ++t);
137
- } else {
138
- t = 1;
116
+ unordered_set<int > s(nums.begin(), nums.end());
117
+ int ans = 0;
118
+ unordered_map<int, int> d;
119
+ for (int x : nums) {
120
+ int y = x;
121
+ while (s.contains(y)) {
122
+ s.erase(y++);
139
123
}
124
+ d[ x] = (d.contains(y) ? d[ y] : 0) + y - x;
125
+ ans = max(ans, d[ x] );
140
126
}
141
127
return ans;
142
128
}
@@ -146,48 +132,39 @@ public:
146
132
#### Go
147
133
148
134
```go
149
- func longestConsecutive(nums []int) int {
150
- n := len(nums)
151
- if n < 2 {
152
- return n
135
+ func longestConsecutive(nums []int) (ans int) {
136
+ s := map[int]bool{}
137
+ for _, x := range nums {
138
+ s[x] = true
153
139
}
154
- sort.Ints(nums)
155
- ans, t := 1, 1
156
- for i, x := range nums[1:] {
157
- if x == nums[i] {
158
- continue
159
- }
160
- if x == nums[i]+1 {
161
- t++
162
- ans = max(ans, t)
163
- } else {
164
- t = 1
140
+ d := map[int]int{}
141
+ for _, x := range nums {
142
+ y := x
143
+ for s[y] {
144
+ delete(s, y)
145
+ y++
165
146
}
147
+ d[x] = d[y] + y - x
148
+ ans = max(ans, d[x])
166
149
}
167
- return ans
150
+ return
168
151
}
169
152
```
170
153
171
154
#### TypeScript
172
155
173
156
``` ts
174
157
function longestConsecutive(nums : number []): number {
175
- const n = nums .length ;
176
- if (n < 2 ) {
177
- return n ;
178
- }
179
- let ans = 1 ;
180
- let t = 1 ;
181
- nums .sort ((a , b ) => a - b );
182
- for (let i = 1 ; i < n ; ++ i ) {
183
- if (nums [i ] === nums [i - 1 ]) {
184
- continue ;
185
- }
186
- if (nums [i ] === nums [i - 1 ] + 1 ) {
187
- ans = Math .max (ans , ++ t );
188
- } else {
189
- t = 1 ;
158
+ const s = new Set (nums );
159
+ let ans = 0 ;
160
+ const d = new Map <number , number >();
161
+ for (const x of nums ) {
162
+ let y = x ;
163
+ while (s .has (y )) {
164
+ s .delete (y ++ );
190
165
}
166
+ d .set (x , (d .get (y ) || 0 ) + (y - x ));
167
+ ans = Math .max (ans , d .get (x )! );
191
168
}
192
169
return ans ;
193
170
}
@@ -196,32 +173,24 @@ function longestConsecutive(nums: number[]): number {
196
173
#### Rust
197
174
198
175
``` rust
199
- use std :: collections :: HashSet ;
176
+ use std :: collections :: { HashMap , HashSet } ;
200
177
201
178
impl Solution {
202
- #[allow(dead_code)]
203
179
pub fn longest_consecutive (nums : Vec <i32 >) -> i32 {
204
- let mut s = HashSet :: new ();
205
- let mut ret = 0 ;
206
-
207
- // Initialize the set
208
- for num in & nums {
209
- s . insert (* num );
210
- }
211
-
212
- for num in & nums {
213
- if s . contains (& (* num - 1 )) {
214
- continue ;
180
+ let mut s : HashSet <i32 > = nums . iter (). cloned (). collect ();
181
+ let mut ans = 0 ;
182
+ let mut d : HashMap <i32 , i32 > = HashMap :: new ();
183
+ for & x in & nums {
184
+ let mut y = x ;
185
+ while s . contains (& y ) {
186
+ s . remove (& y );
187
+ y += 1 ;
215
188
}
216
- let mut cur_num = num . clone ();
217
- while s . contains (& cur_num ) {
218
- cur_num += 1 ;
219
- }
220
- // Update the answer
221
- ret = std :: cmp :: max (ret , cur_num - num );
189
+ let length = d . get (& (y )). unwrap_or (& 0 ) + y - x ;
190
+ d . insert (x , length );
191
+ ans = ans . max (length );
222
192
}
223
-
224
- ret
193
+ ans
225
194
}
226
195
}
227
196
```
@@ -234,22 +203,16 @@ impl Solution {
234
203
* @return {number}
235
204
*/
236
205
var longestConsecutive = function (nums ) {
237
- const n = nums .length ;
238
- if (n < 2 ) {
239
- return n;
240
- }
241
- nums .sort ((a , b ) => a - b);
242
- let ans = 1 ;
243
- let t = 1 ;
244
- for (let i = 1 ; i < n; ++ i) {
245
- if (nums[i] === nums[i - 1 ]) {
246
- continue ;
247
- }
248
- if (nums[i] === nums[i - 1 ] + 1 ) {
249
- ans = Math .max (ans, ++ t);
250
- } else {
251
- t = 1 ;
206
+ const s = new Set (nums);
207
+ let ans = 0 ;
208
+ const d = new Map ();
209
+ for (const x of nums) {
210
+ let y = x;
211
+ while (s .has (y)) {
212
+ s .delete (y++ );
252
213
}
214
+ d .set (x, (d .get (y) || 0 ) + (y - x));
215
+ ans = Math .max (ans, d .get (x));
253
216
}
254
217
return ans;
255
218
};
@@ -261,11 +224,11 @@ var longestConsecutive = function (nums) {
261
224
262
225
<!-- solution: start -->
263
226
264
- ### 方法二:哈希表
227
+ ### 方法二:哈希表(优化)
265
228
266
- 我们用哈希表存储数组中的所有元素,然后遍历数组中的每个元素 $x$,如果当前元素的前驱 $x-1$ 不在哈希表中,那么我们以当前元素为起点,不断尝试匹配 $x+1, x+2, x+3, \dots$,直到匹配不到为止,此时的匹配长度即为以 $x$ 为起点的最长连续序列长度,我们更新答案即可 。
229
+ 与方法一类似,我们用一个哈希表 $\textit{s}$ 存储数组中所有的元素,用一个变量 $\textit{ans}$ 记录最长连续序列的长度。但是,我们不再使用哈希表 $\textit{d}$ 记录每个元素 $x$ 所在的连续序列的长度,在遍历的过程中,跳过那些 $x-1$ 也在哈希表 $\textit{s}$ 中的元素,如果 $x-1$ 在哈希表 $\textit{s}$ 中,那么 $x$ 一定不是连续序列的起点,因此我们可以直接跳过 $x$ 。
267
230
268
- 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组的长度 。
231
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $\textit{nums}$ 的长度 。
269
232
270
233
<!-- tabs: start -->
271
234
@@ -276,7 +239,7 @@ class Solution:
276
239
def longestConsecutive (self , nums : List[int ]) -> int :
277
240
s = set (nums)
278
241
ans = 0
279
- for x in nums :
242
+ for x in s :
280
243
if x - 1 not in s:
281
244
y = x + 1
282
245
while y in s:
@@ -295,7 +258,7 @@ class Solution {
295
258
s. add(x);
296
259
}
297
260
int ans = 0 ;
298
- for (int x : nums ) {
261
+ for (int x : s ) {
299
262
if (! s. contains(x - 1 )) {
300
263
int y = x + 1 ;
301
264
while (s. contains(y)) {
@@ -317,10 +280,10 @@ public:
317
280
int longestConsecutive(vector<int >& nums) {
318
281
unordered_set<int > s(nums.begin(), nums.end());
319
282
int ans = 0;
320
- for (int x : nums ) {
321
- if (!s.count (x - 1)) {
283
+ for (int x : s ) {
284
+ if (!s.contains (x - 1)) {
322
285
int y = x + 1;
323
- while (s.count (y)) {
286
+ while (s.contains (y)) {
324
287
y++;
325
288
}
326
289
ans = max(ans, y - x);
@@ -339,7 +302,7 @@ func longestConsecutive(nums []int) (ans int) {
339
302
for _, x := range nums {
340
303
s[x] = true
341
304
}
342
- for _, x := range nums {
305
+ for x, _ := range s {
343
306
if !s[x-1] {
344
307
y := x + 1
345
308
for s[y] {
@@ -356,7 +319,7 @@ func longestConsecutive(nums []int) (ans int) {
356
319
357
320
``` ts
358
321
function longestConsecutive(nums : number []): number {
359
- const s: Set < number > = new Set (nums );
322
+ const s = new Set < number > (nums );
360
323
let ans = 0 ;
361
324
for (const x of s ) {
362
325
if (! s .has (x - 1 )) {
@@ -371,6 +334,29 @@ function longestConsecutive(nums: number[]): number {
371
334
}
372
335
```
373
336
337
+ #### Rust
338
+
339
+ ``` rust
340
+ use std :: collections :: HashSet ;
341
+
342
+ impl Solution {
343
+ pub fn longest_consecutive (nums : Vec <i32 >) -> i32 {
344
+ let s : HashSet <i32 > = nums . iter (). cloned (). collect ();
345
+ let mut ans = 0 ;
346
+ for & x in & s {
347
+ if ! s . contains (& (x - 1 )) {
348
+ let mut y = x + 1 ;
349
+ while s . contains (& y ) {
350
+ y += 1 ;
351
+ }
352
+ ans = ans . max (y - x );
353
+ }
354
+ }
355
+ ans
356
+ }
357
+ }
358
+ ```
359
+
374
360
#### JavaScript
375
361
376
362
``` js
0 commit comments