最长连续序列
给定一个未排序的整数数组 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
示例 3:
输入:nums = [1,0,1,2]
输出:3
提示:
0 <= nums.length <= 105-109 <= nums[i] <= 109
解题思路
哈希去重
算法思路
这个解法的关键是利用哈希缓存避免重复遍历:
先用 HashSet 存储所有数字,利用其
O(1)时间复杂度的查询特性;只从「连续序列的起点」(即某个数字
num不存在num-1时)开始,向后逐个查找num+1、num+2...,统计当前序列长度;全程维护最大长度,最终返回结果。
代码逻辑详解
class Solution {
public int longestConsecutive(int[] nums) {
// 步骤1:创建HashSet并存储所有数字,去重+快速查询
Set<Integer> cache = new HashSet();
for (int num : nums) {
cache.add(num);
}
// 步骤2:初始化最长连续序列长度为0
int maxLength = 0;
// 步骤3:遍历集合中的每个数字(已去重)
for (int num : cache) {
// 核心判断:当前数字是否是「连续序列的起点」
// 只有当num-1不存在时,才是起点,避免重复计算
if (!cache.contains(num - 1)) {
int temp = num + 1; // 从num的下一个数字开始查
int tempMaxLength = 1; // 起点自身长度为1
// 循环查找后续连续数字,统计当前序列长度
while (cache.contains(temp)) {
tempMaxLength++; // 找到一个,长度+1
temp++; // 继续查下一个数字
}
// 更新全局最长长度
maxLength = Math.max(maxLength, tempMaxLength);
}
// 如果num-1存在,说明num不是起点,直接跳过,避免重复遍历
}
// 步骤4:返回最长连续序列长度
return maxLength;
}
}排序 + 动态规划
算法思路
这段代码采用排序 + 动态规划的思路:
先把数组排序,让连续的数字挨在一起
用一个
result数组记录「以当前数字结尾的最长连续序列长度」遍历数组,根据当前数字和前一个数字的关系,更新
result值,同时记录最大值
代码逻辑详解
class Solution {
public int longestConsecutive(int[] nums) {
// 步骤1:先对数组排序,让连续的数字相邻
Arrays.sort(nums);
// 步骤2:初始化最大值为0(处理空数组的情况)
int max = 0;
// 步骤3:创建result数组,长度和nums一致,每个元素初始值为1
// 因为每个数字自身至少是一个长度为1的连续序列
int[] result = new int[nums.length];
Arrays.fill(result, 1);
// 步骤4:遍历数组,逐个判断连续关系
for (int i = 0; i < nums.length; i++) {
// 处理第一个元素:没有前一个元素,直接更新max
if (i == 0) {
max = Math.max(max, result[i]);
continue;
}
// 情况1:当前数字 = 前一个数字 + 1 → 连续,更新result[i]
if (nums[i] == nums[i - 1] + 1) {
result[i] = result[i - 1] + 1; // 继承前一个的长度并+1
max = Math.max(max, result[i]); // 更新全局最大值
continue;
}
// 情况2:当前数字 = 前一个数字 → 重复,长度和前一个一致
if (nums[i] == nums[i - 1]){
result[i] = result[i - 1];
continue;
}
// 情况3:既不连续也不重复 → 保持初始值1,无需额外处理
}
// 步骤5:返回最长连续序列的长度
return max;
}
}