@@ -53,19 +53,15 @@ tags:
5353
5454<!-- solution:start -->
5555
56- ### 方法一:排序
56+ ### 方法一:哈希表
5757
58- 我们先将数组排序,然后用一个变量 $t$ 记录当前连续序列的长度 ,用一个变量 $ans$ 记录最长连续序列的长度。
58+ 我们可以用一个哈希表 $\textit{s}$ 存储数组中所有的元素 ,用一个变量 $\textit{ ans} $ 记录最长连续序列的长度,用一个哈希表 $\textit{d}$ 记录每个元素 $x$ 所在的连续序列的长度 。
5959
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 ] )$。
6161
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}$ 即可。
6563
66- 最终,我们返回答案 $ans$ 即可。
67-
68- 时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 是数组的长度。
64+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $\textit{nums}$ 的长度。
6965
7066<!-- tabs:start -->
7167
@@ -74,19 +70,16 @@ tags:
7470``` python
7571class Solution :
7672 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])
9083 return ans
9184```
9285
@@ -95,21 +88,19 @@ class Solution:
9588``` java
9689class Solution {
9790 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) ;
10194 }
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++ );
112101 }
102+ d. put(x, d. getOrDefault(y, 0 ) + y - x);
103+ ans = Math . max(ans, d. get(x));
113104 }
114105 return ans;
115106 }
@@ -122,21 +113,16 @@ class Solution {
122113class Solution {
123114public:
124115 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++);
139123 }
124+ d[ x] = (d.contains(y) ? d[ y] : 0) + y - x;
125+ ans = max(ans, d[ x] );
140126 }
141127 return ans;
142128 }
@@ -146,48 +132,39 @@ public:
146132#### Go
147133
148134```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
153139 }
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++
165146 }
147+ d[x] = d[y] + y - x
148+ ans = max(ans, d[x])
166149 }
167- return ans
150+ return
168151}
169152```
170153
171154#### TypeScript
172155
173156``` ts
174157function 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 ++ );
190165 }
166+ d .set (x , (d .get (y ) || 0 ) + (y - x ));
167+ ans = Math .max (ans , d .get (x )! );
191168 }
192169 return ans ;
193170}
@@ -196,32 +173,24 @@ function longestConsecutive(nums: number[]): number {
196173#### Rust
197174
198175``` rust
199- use std :: collections :: HashSet ;
176+ use std :: collections :: { HashMap , HashSet } ;
200177
201178impl Solution {
202- #[allow(dead_code)]
203179 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 ;
215188 }
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 );
222192 }
223-
224- ret
193+ ans
225194 }
226195}
227196```
@@ -234,22 +203,16 @@ impl Solution {
234203 * @return {number}
235204 */
236205var 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++ );
252213 }
214+ d .set (x, (d .get (y) || 0 ) + (y - x));
215+ ans = Math .max (ans, d .get (x));
253216 }
254217 return ans;
255218};
@@ -261,11 +224,11 @@ var longestConsecutive = function (nums) {
261224
262225<!-- solution: start -->
263226
264- ### 方法二:哈希表
227+ ### 方法二:哈希表(优化)
265228
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$ 。
267230
268- 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组的长度 。
231+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $\textit{nums}$ 的长度 。
269232
270233<!-- tabs: start -->
271234
@@ -276,7 +239,7 @@ class Solution:
276239 def longestConsecutive (self , nums : List[int ]) -> int :
277240 s = set (nums)
278241 ans = 0
279- for x in nums :
242+ for x in s :
280243 if x - 1 not in s:
281244 y = x + 1
282245 while y in s:
@@ -295,7 +258,7 @@ class Solution {
295258 s. add(x);
296259 }
297260 int ans = 0 ;
298- for (int x : nums ) {
261+ for (int x : s ) {
299262 if (! s. contains(x - 1 )) {
300263 int y = x + 1 ;
301264 while (s. contains(y)) {
@@ -317,10 +280,10 @@ public:
317280 int longestConsecutive(vector<int >& nums) {
318281 unordered_set<int > s(nums.begin(), nums.end());
319282 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)) {
322285 int y = x + 1;
323- while (s.count (y)) {
286+ while (s.contains (y)) {
324287 y++;
325288 }
326289 ans = max(ans, y - x);
@@ -339,7 +302,7 @@ func longestConsecutive(nums []int) (ans int) {
339302 for _, x := range nums {
340303 s[x] = true
341304 }
342- for _, x := range nums {
305+ for x, _ := range s {
343306 if !s[x-1] {
344307 y := x + 1
345308 for s[y] {
@@ -356,7 +319,7 @@ func longestConsecutive(nums []int) (ans int) {
356319
357320``` ts
358321function longestConsecutive(nums : number []): number {
359- const s: Set < number > = new Set (nums );
322+ const s = new Set < number > (nums );
360323 let ans = 0 ;
361324 for (const x of s ) {
362325 if (! s .has (x - 1 )) {
@@ -371,6 +334,29 @@ function longestConsecutive(nums: number[]): number {
371334}
372335```
373336
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+
374360#### JavaScript
375361
376362``` js
0 commit comments