目录
- 题目
- 伪代码
- [Python 实现](#Python 实现)
- 算法复杂度
- 核心知识点
- 流程示例
- 常见误区
题目
给定一个未排序 的整数数组 nums,找出数字连续 的最长序列(元素不要求在原数组中连续)的长度。
要求 :设计并实现 时间复杂度 O(n) 的算法。
示例
| 输入 |
输出 |
解释 |
[100,4,200,1,3,2] |
4 |
最长序列 [1,2,3,4] |
[0,3,7,2,5,8,4,6,0,1] |
9 |
[0,1,2,3,4,5,6,7,8] |
[1,0,1,2] |
3 |
[0,1,2] |
伪代码
复制代码
算法 longestConsecutive(nums)
输入:整数数组 nums
输出:最长连续序列长度
1 S ← 将 nums 转为集合 // 去重 + O(1) 查找
2 maxLen ← 0 // 全局最长长度
3 对于 num 属于 S 执行 // 遍历每个唯一值
4 若 num-1 ∉ S 则 // 仅当 num 是"起点"才进入内循环
5 cur ← num
6 len ← 1
7 当 cur+1 ∈ S 执行 // 向后扩张
8 cur ← cur+1
9 len ← len+1
10 maxLen ← max(maxLen, len)
11 返回 maxLen
Python 实现
python
复制代码
from typing import List
class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
# 1. 去重 + 哈希,保证每个数字只处理一次
num_set = set(nums) # O(n) 空间
longest_streak = 0 # 2. 全局最优解
# 3. 遍历集合,每个元素只访问一次外循环
for num in num_set:
# 4. 【贪心剪枝】只有 num 是序列起点才进入内循环
# 这样确保每条连续段只被处理一次
if num - 1 not in num_set:
current_num = num # 5. 当前段起点
current_streak = 1 # 6. 当前段长度
# 7-9. 向后扩张,集合查找 O(1)
while current_num + 1 in num_set:
current_num += 1
current_streak += 1
# 10. 更新全局最优
longest_streak = max(longest_streak, current_streak)
# 11. 返回结果
return longest_streak
算法复杂度
| 维度 |
结论 |
证明 |
| 时间 |
O(n) |
每个数字最多被访问 2 次 (外循环 1 次,内循环作为 cur+1 1 次),集合查询 O(1) → 总时间 2n·O(1)=O(n)。 |
| 空间 |
O(n) |
哈希集合 num_set 存储所有唯一元素,最坏 n 个。 |
核心知识点
| 名称 |
作用 |
本题体现 |
| 哈希表 / 集合 |
近似 O(1) 查询 |
快速判断 num±1 是否存在 |
| 贪心策略 |
只做"必要"工作 |
仅当 num-1 不存在时才以 num 为起点,避免重复扫描 |
| 起点剪枝 |
保证每条连续段只处理一次 |
将总体复杂度从 O(n²) 降到 O(n) |
| 空间换时间 |
用额外内存换取查询速度 |
用 set 存储全部元素 |
流程示例
输入 :nums = [100, 4, 200, 1, 3, 2]
集合 :S = {1, 2, 3, 4, 100, 200}
- 起点判断:
- 1 是起点 → 扩张得
[1,2,3,4],长度 4
- 100 是起点 → 仅
[100],长度 1
- 200 是起点 → 仅
[200],长度 1
结果 :maxLen = 4
常见误区
| 误区 |
后果 |
| 直接排序 |
时间升至 O(n log n),不满足题目要求 |
| 不判起点 |
每个元素都触发内循环,复杂度退化至 O(n²) |
| 忽略去重 |
重复数字导致内循环重复统计,结果可能偏大 |
复制代码