Skip to content

Commit 9479b94

Browse files
authored
feat: add solutions to lc problem: No.0128 (#3891)
No.0128.Longest Consecutive Sequence
1 parent 312ee51 commit 9479b94

18 files changed

+332
-378
lines changed

solution/0000-0099/0001.Two Sum/README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,7 @@ class Solution:
8585
def twoSum(self, nums: List[int], target: int) -> List[int]:
8686
d = {}
8787
for i, x in enumerate(nums):
88-
y = target - x
89-
if y in d:
88+
if (y := target - x) in d:
9089
return [d[y], i]
9190
d[x] = i
9291
```

solution/0000-0099/0001.Two Sum/README_EN.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,7 @@ class Solution:
8282
def twoSum(self, nums: List[int], target: int) -> List[int]:
8383
d = {}
8484
for i, x in enumerate(nums):
85-
y = target - x
86-
if y in d:
85+
if (y := target - x) in d:
8786
return [d[y], i]
8887
d[x] = i
8988
```

solution/0000-0099/0001.Two Sum/Solution.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ class Solution:
22
def twoSum(self, nums: List[int], target: int) -> List[int]:
33
d = {}
44
for i, x in enumerate(nums):
5-
y = target - x
6-
if y in d:
5+
if (y := target - x) in d:
76
return [d[y], i]
87
d[x] = i

solution/0100-0199/0128.Longest Consecutive Sequence/README.md

+112-126
Original file line numberDiff line numberDiff line change
@@ -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
7571
class 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
9689
class 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 {
122113
class Solution {
123114
public:
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
174157
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++);
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

201178
impl 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
*/
236205
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++);
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
358321
function 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

Comments
 (0)