1. 同样是求“连续”,为什么普通遍历会超时
1.1 题面到底在说什么
“最长连续序列”这道题,刷过 LeetCode 的人应该都不陌生。题目原话大致是:给你一个未排序的整数数组 nums,请你找出数字连续的最长序列的长度,并且要求算法时间复杂度为 O(n)。
这里的“数字连续”有很多人理解错。比如输入 [100, 4, 200, 1, 3, 2],正确答案是 4,也就是 [1, 2, 3, 4]。它并不要求在数组里这些数字是按顺序相邻存在的,只要数值上能连成一条递增的整数链,而且链上的每一个整数都真实出现在原数组里,就算一个连续序列。
再比如 [0, 3, 7, 2, 5, 8, 4, 6, 0, 1] 这个例子,数组里面出现了 0 到 8 的所有整数,虽然原数组顺序打得很散,但答案就是 9。因为从 0 一路数到 8,每个数字都在数组里存在。
这道题看起来像“找最大连续区间”,但本质上是一个集合查询问题。我们需要回答的是:给定一个数字哈希集合,是否存在从某个最小值开始、以步长 1 递增延伸的完整区间,以及这个区间最长能有多长。
我第一次刷到这道题时,第一反应和大多数人一样:排序。排完序后,挨个检查相邻数字是不是差 1,一路数过去就行。这个方案确实能把题目做出来,而且写起来不容易错。但问题也很明显:排序已经让时间复杂度变成了 O(n log n),根本达不到题目要求的 O(n)。
后来我才慢慢理解,面试官问这道题,表面上考的是“你会不会处理数组”,实际考的是三个层次:能不能想到用哈希集合去重,能不能想到从连续区间的最小值开始扩展,以及能不能把时间复杂度证明清楚。最后这一点才是分水岭。
1.2 别急着上set,先理解“盲目扩展”会造成什么后果
很多人知道要用哈希集合后,会写下这样一版代码:先把所有数字塞进 set,然后遍历 set 里的每个数字,用 while 循环不断把当前数字加 1,看它在不在集合里,在的话长度加 1,最后更新最大值。
这个思路方向是对的,但复杂度是错的。如果数组是 [1, 2, 3, ..., n],遍历到 1 的时候,内部 while 会一直加到 n,统计出 n 的长度;遍历到 2 的时候,又会从 2 一直加到 n,又统计出一个 n-1 的长度;遍历到 3 的时候,再重复一次。最终整体耗时接近于 n 的平方。
为什么会这样?因为每个连续区间被重复计算了多次。每个数字都当了一次“开头”,但实际上只有区间里的最小值才有资格当开头。其他数字虽然也能通过 while 找出一段连续序列,但那只是把别人统计过的区间又走了一遍,属于纯浪费。
所以这道题的技术核心,不是“用 set 判断存在性”,而是“如何保证每个区间只被统计一次”。只要这个问题想明白了,代码其实很短。在这个意义下,它又是一道典型的“想清楚思路比写代码更难”的题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 先从排序版解法入手:能过用例,但没答到题眼上
2.1 排序加单遍扫描的代码
排序版解法是我建议初学者先写一遍的版本,因为它最直观,也最不容易出逻辑漏洞。思路就三步:先对数组排序,排序之后相同或相近的数字会靠到一起;然后从左到右扫描,如果当前数字等于上一个数字,说明是重复项,直接跳过;如果当前数字正好比上一个数字大 1,说明连续段还在延续,计数器加 1;否则说明连续段断了,先把当前长度更新到结果里,再把计数器重置成 1。
Python 实现大概是这样的:
python复制def longestConsecutive_sort(nums):
if not nums:
return 0
nums.sort()
longest = 1
current_len = 1
for i in range(1, len(nums)):
if nums[i] == nums[i - 1]:
continue
elif nums[i] ==
