LOADING

加载过慢请开启缓存 浏览器默认开启

最长连续序列

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

示例 3:

输入:nums = [1,0,1,2]
输出:3

提示:

  • 0 <= nums.length <= 10^5
  • -10^9 <= nums[i] <= 10^9

拿到这道题的一开始还准备直接开辟10001的数组仿制哈希set来解决,没想到忘记了负数的存在,并且这道题是10^9开不了那么大的数

本题的核心是发掘hashSet的本质特点,hashSet的特点是什么呢?那么这道题是如何借助hashSet的特点来解决的呢?

只知道解法还是不够,得知道解决问题的本质,于是我问了chatGpt

chatGPT:

这个问题问得非常深入,非常 INFJ 式地想挖“本质与灵感来源”,我来尽量用你喜欢的方式解释:


✅ 一、HashSet 被用到的两个关键“性质”

🌟 1. 快速查找 O(1) —— set.contains(x)

判断一个数是否存在,不用遍历,直接查,时间复杂度 O(1)

这是最关键的特性。因为我们需要在序列中判断一个数的“前一个”或“后一个”是否存在,HashSet 能极快完成这个判断。


🌟 2. 去重

数组里可能有重复项,HashSet 自动帮你去重

这对于 nums = [1,0,1,2] 这种输入是必要的,否则你可能会重复处理。


✅ 二、这道题的“感觉”或“直觉”

很多人第一反应会是:排序 → 然后遍历。但排序是 O(nlogn),不符合要求。

而这道题的 直觉点在于

🌱“只要我知道一个连续序列的起点,我就可以一路 +1 找下去。”


💡 于是我们思考:

如果我能快速知道一个数是否在原数组中,那我就能从每个可能的起点 x 出发,查 x+1, x+2...,直到查不到为止。

但怎么快速查?
👉 这就自然想到 HashSet!


✅ 所以,问题就转化成了:

  • 先把所有数字放到 set 中
  • 从每个“可能的起点”出发往右找

🚩 如何判断某个数是“起点”?

答案是:

java


复制编辑
if (!set.contains(num - 1))

也就是:

只有当 num-1 不存在时,num 才是这个连续序列的第一个数。

这样就保证了每个序列只被处理一次,时间复杂度 O(n)。


✅ 总结:为什么 HashSet 是灵魂

特性 在这道题中的作用
查找快 O(1) 快速判断某个数是否存在
去重 防止重复处理同一个数字
空间换时间 用 O(n) 空间换 O(n) 时间
语义契合 “是否存在”的判断语义就是 Set 本质

🌌 最后的“感觉”总结一句话:

这道题的关键感受是:“我需要快速判断一个数字是否存在”,这种需求一出现,HashSet 就成了最自然的选择,它的 contains() 就像“意识的触角”一样可以立刻知晓答案。

public static int longestConsecutive(int[] nums) {
    HashSet<Integer> set = new HashSet<>();
    int ans=0;
    for (int i = 0; i < nums.length; i++) {
        if(!set.contains(nums[i])) {
            set.add(nums[i]);
        }
    }
    for (Integer i : set) {
        if(!set.contains(i-1)) {
            int cur=i;
            int len=1;
            while(set.contains(cur+1)) {
                len++;
                cur++;
            }
            ans = Math.max(ans, len);
        }
    }
    return ans;
}