128. 最长连续序列

128. 最长连续序列

✨核心逻辑

本题要求在 时间复杂度 O(N) 的约束下解决问题,因此不能使用常规的排序方法(排序最低也是 O(N log N))。这里采用 哈希集合(HashSet)优化查找 的策略:

  1. 去重并快速查找:将数组中的所有数字放入一个 HashSet 中。这样可以在 O(1) 的时间内判断某个数字是否存在。
  2. 找连续序列的起点:遍历集合中的每一个数字。如果当前数字 integer - 1 存在于集合中,说明 integer 不是一段连续序列的起点(它是序列中间或末尾的元素),我们直接跳过它,不做处理。
  3. 从起点向后探测:只有当 integer - 1 不存在时,说明 integer 是一段连续序列的起点。此时我们利用 while 循环不断向后寻找 num + 1,统计出这段连续序列的长度。
  4. 更新最大长度:每次统计完一段连续序列的长度后,与当前记录的全局最大长度 max1 进行比较并更新。

这种方法确保了大循环中的 while 探测,在整个算法执行过程中,集合中的每个数字最多只会被访问一次,总体时间复杂度被降低到了 O(N)

🔥代码实现(含详细变量注释)

class Solution {
    public int longestConsecutive(int[] nums) {
        // set:哈希集合,用于存储数组中的所有元素,去除重复值,同时提供 O(1) 的查找性能
        Set<Integer> set = new HashSet<>();
        for (int i : nums) {
            set.add(i);
        }
        
        // max1:记录当前发现的最长连续序列的长度,初始值为 0
        int max1 = 0;
        
        // 遍历哈希集合中的每一个数字
        for (Integer integer : set) {
            // 核心优化:判断当前数字 integer 是否为一段连续序列的起点
            // 如果集合中存在 integer - 1,说明当前数字不是序列的起点,直接跳过,避免重复计算
            if (!set.contains(integer - 1)) {
                // num:从当前起点开始,用于不断向后寻找连续的下一个数字
                int num = integer;
                // max2:记录当前探测到的这段连续序列的长度,初始为 1(包含自身)
                int max2 = 1;
                
                // 只要集合中存在 num + 1,说明连续关系还在继续
                while (set.contains(num + 1)) {
                    num = num + 1; // 往后推一位
                    max2++;        // 当前连续序列长度 +1
                }
                
                // 更新全局最大连续序列的长度
                max1 = Math.max(max1, max2);
            }
        }
        // 返回找到的最长连续序列的长度
        return max1;
    }
}

  • ⏱️复杂度分析
    • 时间复杂度:O(N),其中 N 是数组的长度。虽然代码中有双层嵌套循环结构(外层 for 套内层 while),但由于我们只从序列的起点开始遍历,内层 while 循环在整个程序的执行过程中,集合中的每个元素最多只会被访问一次。因此总操作次数与数组元素总数成正比。

    • 空间复杂度:O(N),额外使用了一个哈希集合 set 来存储数组中的所有元素,所需空间与输入数组的大小线性相关。

🔍总结一下:

int的范围是 -2.1的10^9 到 2.1的10^9,需要记一下,有些题会给10的多少次方的范围

疑问点:时间复杂度是O n方,举个例子,直观的123456

真正的 N方 是指每个元素走到时,都要重复去遍历所有元素;但这道题的连续序列 [1,2,3,4,5,6] 中,只有起点 1 触发了 while 并一次性地扫完了 2,3,4,5,6。当外层循环走到 2,3,4,5,6 时,它们遇到前面的 if 判断直接就被‘判出局’了,连内层 while 的大门都没进去。真正走完的直有最开始的 1