LeetCode 第 128 题「最长连续序列」
字数 1055 2025-10-25 23:40:26
我来给你讲解 LeetCode 第 128 题「最长连续序列」。
题目描述
给定一个未排序的整数数组 nums,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
要求时间复杂度为 O(n)。
示例 1:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长连续序列是 [1, 2, 3, 4],长度为 4。
示例 2:
输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9
解题思路
1. 暴力思路(不可行)
如果先排序,再扫描一遍找最长连续序列,时间复杂度是 O(n log n),但题目要求 O(n)。
如果对每个数字,都尝试找它之后的连续数字,最坏情况 O(n²),也不满足要求。
2. 关键观察
我们要找的是连续的数字,例如 [1,2,3,4] 这样的序列。
连续序列的特点是:序列中的最小值 x,在数组中不存在 x-1。
例如:
- 对于数字
1,没有0,那么可以从1开始往后找2,3,4,...。 - 对于数字
2,存在1,所以它不可能是某个连续序列的起点,跳过。
这样,每个连续序列我们只从它的起点开始枚举一次,避免重复计算。
3. 算法步骤
- 将所有数字放入一个哈希集合(set),以便 O(1) 时间判断某个数是否存在。
- 遍历数组中的每个数字
num:- 如果
num - 1存在于集合中,说明num不是某个连续序列的起点,跳过。 - 如果
num - 1不存在,则num是起点,开始向后枚举num+1, num+2, ...直到某个数不在集合中为止,记录长度。
- 如果
- 所有长度中的最大值即为答案。
4. 为什么是 O(n) 时间复杂度?
虽然有一个内层循环在枚举连续数字,但每个数字最多被内层循环访问一次(因为只有起点才会进入内层循环,并且每个连续序列只被起点枚举一次),所以总时间复杂度是 O(n)。
举例说明
以 nums = [100,4,200,1,3,2] 为例:
- 建立集合:
{100,4,200,1,3,2}。 - 遍历:
- 100:99 不在集合中,是起点,向后找 101 不在,长度=1。
- 4:3 在集合中,跳过。
- 200:199 不在集合中,是起点,向后找 201 不在,长度=1。
- 1:0 不在集合中,是起点,向后找 2 在,3 在,4 在,5 不在,长度=4。
- 3:2 在集合中,跳过。
- 2:1 在集合中,跳过。
- 最大长度 = 4。
代码实现(伪代码/思路)
def longestConsecutive(nums):
if not nums:
return 0
num_set = set(nums)
longest = 0
for num in num_set:
# 只有当 num 是序列起点时才进入内循环
if num - 1 not in num_set:
current_num = num
current_streak = 1
while current_num + 1 in num_set:
current_num += 1
current_streak += 1
longest = max(longest, current_streak)
return longest
复杂度
- 时间复杂度:O(n),每个元素最多被内外层循环各访问一次。
- 空间复杂度:O(n),用于存储哈希集合。
这样,我们就用 O(n) 时间解决了“最长连续序列”问题。