面试经典150题[047]:最长连续序列(LeetCode 128)
最长连续序列(LeetCode 128)
题目链接:最长连续序列(LeetCode 128)
难度:困难
1. 题目描述
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
提示:
- 0 <= nums.length <= 10^5
- -10^9 <= nums[i] <= 10^9
示例:
输入: nums = [100,4,200,1,3,2]
输出: 4
解释: 最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
输入: nums = [0,3,7,2,5,8,4,6,0,1]
输出: 9
输入: nums = [1,0,1,2]
输出: 3
2. 问题分析
2.1 规律
- 数组未排序,可能包含重复元素,且元素范围很大(-10^9 到 10^9),不允许使用排序(否则时间复杂度为 O(n log n))。
- 核心问题:找出最长的连续整数序列(如 1,2,3,4),序列不需在数组中连续出现,只需数字值连续。
- 由于保证 O(n) 时间,必须避免对每个元素进行多次遍历或嵌套循环。
- 处理重复:重复元素不影响序列长度(如 [1,1] 的最长序列长度为 1)。
- 边界情况:空数组返回 0;单个元素返回 1;所有元素相同返回 1。
2.2 贪心思路
我们使用哈希集合(set)来实现 O(1) 查询:
- 将所有元素放入集合中,去除重复,同时确保查询任意数字是否存在为 O(1)。
- 遍历集合中的每个数字 num,只有当 num 是序列的起点(即 num-1 不存在于集合中)时,才从 num 开始向上计数连续序列。
- 对于每个起点,初始化 current_length = 1,然后检查 num+1, num+2, … 是否存在,逐一累加长度。
- 更新全局最大长度 max_length。
- 为什么 O(n)?每个元素只被插入一次、遍历一次,且在计数过程中,每个元素只被检查一次(序列只从起点开始遍历,不会重复计数中间元素)。
3. 代码实现
Python
class Solution:def longestConsecutive(self, nums):if not nums:return 0num_set = set(nums)max_length = 0for num in num_set:if num - 1 not in num_set: # 只有起点才开始计数current_num = numcurrent_length = 1while current_num + 1 in num_set:current_num += 1current_length += 1max_length = max(max_length, current_length)return max_length
C++
#include <unordered_set>
#include <vector>
#include <algorithm>class Solution {
public:int longestConsecutive(std::vector<int>& nums) {if (nums.empty()) return 0;std::unordered_set<int> num_set(nums.begin(), nums.end());int max_length = 0;for (int num : num_set) {if (num_set.find(num - 1) == num_set.end()) { // 只有起点才开始计数int current_num = num;int current_length = 1;while (num_set.find(current_num + 1) != num_set.end()) {current_num++;current_length++;}max_length = std::max(max_length, current_length);}}return max_length;}
};
4. 复杂度分析
- 时间复杂度:O(n),集合插入和遍历均为 O(n),计数过程总计 O(n)(每个元素最多被访问一次)。
- 空间复杂度:O(n),用于存储集合。
5. 总结
- 连续序列问题 + O(n) 时间 → 哈希集合 + 贪心起点检测是首选。
- 核心维护起点和连续计数,很通用。
- 类似图的连通组件,但优化为线性时间。
- 可扩展到处理重复或大范围数值的变体。
复习
面试经典150题[017]:罗马数字转整数(LeetCode 13)
面试经典150题[032]:串联所有单词的子串(LeetCode 30)