128.最长连续序列128.最长连续序列
我的题解:通过排序+计数的方式进行完成。开始我用的是自己写的冒泡排序来进行排序但是后续运行发现时间复杂度过高运行超时就用系统自带的了(后续会去学一手时间复杂度低的排序)
128.最长连续序列
class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
if not nums:
return 0
dic_num = collections.defaultdict(list)
col=[0]*len(nums)
nums_s=sorted(nums)
for i,num in enumerate(nums_s):
if num not in dic_num:
dic_num[num].append(i)
col[i]+=1
if num-1 in dic_num:
col[i]=col[i-1]+1
else:
col[i]=col[i-1]
ma=max(col)
return ma
官方题解:
方法一:哈希表
这段代码实现了 O(n) 时间复杂度 的“最长连续序列”算法,核心思想是:只从每个连续序列的起点开始计数,避免重复遍历。下面逐行解析逻辑(不包括类和函数定义):
1. 初始化结果变量
longest_streak = 0
- 用于记录全局最长的连续序列长度。
2. 将输入转为集合(哈希表)
num_set = set(nums)
- 去重:消除重复数字对连续性判断的干扰;
- O(1) 查找:后续可通过
in操作快速判断某个数字是否存在。
3. 遍历集合中的每个数字
for num in num_set:
- 注意:遍历的是去重后的数字,避免无效重复计算。
4. 判断是否为连续序列的“起点”
if num - 1 not in num_set:
- 关键优化:只有当
num - 1不存在时,num才是一个连续序列的起始点。 - 举例:
- 若集合中有
[100, 4, 200, 1, 3, 2], - 当
num = 1时,0不在集合中 → 是起点; - 当
num = 2时,1在集合中 → 不是起点,跳过。
- 若集合中有
- 这样确保每个连续序列只被完整遍历一次,总时间复杂度为 O(n)。
5. 从起点开始向后扩展
current_num = num
current_streak = 1
current_num:当前检查的数字;current_streak:当前连续序列的长度(至少为 1,包含起点自身)。
6. 向右延伸连续序列
while current_num + 1 in num_set:
current_num += 1
current_streak += 1
- 不断检查下一个整数(
current_num + 1)是否存在于集合中; - 如果存在,序列长度加 1,并继续向后探测;
- 直到找不到下一个连续数字为止。
例如:起点
num = 1,集合中有2, 3, 4,则循环会依次找到2→3→4,最终current_streak = 4。
7. 更新全局最长长度
longest_streak = max(longest_streak, current_streak)
- 每次完成一个连续序列的探测后,更新全局最大值。
✅ 算法优势总结
| 特点 | 说明 |
|---|---|
| 时间复杂度 O(n) | 每个数字最多被访问两次(一次在外层循环,一次在 while 中),均摊 O(1) |
| 空间复杂度 O(n) | 需要额外集合存储去重后的数字 |
| 无需排序 | 完全基于哈希查找,避免 O(n log n) 排序开销 |
| 自动去重 | 集合天然消除重复元素干扰 |
🧪 示例演示
输入:nums = [100, 4, 200, 1, 3, 2]
num_set = {1, 2, 3, 4, 100, 200}
num = 100:99不在 → 序列[100]→ 长度 1num = 4:3在 → 跳过num = 200:199不在 → 序列[200]→ 长度 1num = 1:0不在 → 序列[1,2,3,4]→ 长度 4num = 3:2在 → 跳过num = 2:1在 → 跳过
最终结果:4
💡 关键洞察
“只从起点开始计数” 是本解法的核心。
它避免了对[1,2,3,4]中的2,3,4分别做无用遍历,从而将暴力 O(n²) 优化到 O(n)。
100题:128.最长连续序列&spm=1001.2101.3001.5002&articleId=154521785&d=1&t=3&u=350a970f199a4e4db7db6e1ef15d375c)
1285

被折叠的 条评论
为什么被折叠?



