hot100 最长连续序列(128)

class Solution {
    public int longestConsecutive(int[] nums) {
        Set<Integer> set = new HashSet<>();
        for (int num : nums) {
            set.add(num);
        }
        int ans = 0;
        for (int x : set) {
            if (!set.contains(x - 1)) {
                int temp = 1;
                int cur = x;
                while (set.contains(cur + 1)) {
                    temp++;
                    cur++;
                }
                ans = Math.max(ans, temp);
            }
        }
        return ans;
    }
}

一、 算法核心设计思想

该算法的核心在于解决两个效率瓶颈:去重与快速查找避免重复枚举序列

1. 哈希表去重与常数级查找

在未排序数组中查找一个元素是否存在,常规的暴力查找需要 O(n)时间,而排序需要 O(n \log n)时间。本解法首先将所有元素存入 HashSet

  • 去重: 消除数组中重复数字对计数造成的干扰(如示例 3 中的重复 1)。

  • 常数查找: HashSetcontains 操作在平均情况下的时间复杂度为 O(1),这为后续的连续性检测提供了高效率支持。

2. 核心剪枝逻辑:定位序列起点

算法的核心突破点在于 if (!set.contains(x - 1)) 这一行判断。

  • 逻辑含义: 对于集合中的某个数字 x,如果 x - 1 已经存在于集合中,说明 x 绝对不是某个连续序列的开头,它只是某个更长序列的中间元素。

  • 执行策略: 只有当 x - 1 不在集合中时,才认定 x 是一个序列的起点(最小值),此时才启动 while 循环向后延伸查找 x + 1, x + 2, \dots。

  • 效果: 这一步剪枝彻底改变了算法的复杂度,确保了每个连续序列只会被完整遍历一次。

二、 算法执行流程拆解

以示例 1 为例:nums = [100, 4, 200, 1, 3, 2]

步骤 1:构建哈希集合

遍历 nums,存入 HashSet,此时 set = {100, 4, 200, 1, 3, 2}

步骤 2:遍历集合并计数

外层循环遍历 set 中的每个元素 x(以输入 nums = [100, 4, 200, 1, 3, 2] 为例):

当前元素 xset.contains(x - 1) 结果是否触发 while 循环内部 while 循环过程与计数局部长度 temp全局最大长度 ans
100contains(99)是 (起点)查找 101 不存在,循环直接结束1max(0, 1) = 1
4contains(3)否 (跳过)无(4 不是序列起点,跳过)-1
200contains(199)是 (起点)查找 201 不存在,循环直接结束1max(1, 1) = 1
1contains(0)是 (起点)

依次查找 2, 3, 4 均存在,5 不存在。

 

连续序列为:1 → 2 → 3 → 4

4max(1, 4) = 4
3contains(2)否 (跳过)无(3 不是序列起点,跳过)-4
2contains(1)否 (跳过)无(2 不是序列起点,跳过)-4

最终返回: ans = 4

三、 复杂度分析

1. 时间复杂度:$O(n)$

虽然代码结构中存在一个 while 循环嵌套在 for 循环内部,通常这种结构可能导致 $O(n^2)$ 的复杂度,但由于剪枝条件的存在,其总体时间复杂度为 $O(n)$。

  • 外层循环: 遍历 set 中的每个独立元素,共执行 $n$ 次(准确说是 $U$ 次, $U$ 为去重后的元素个数,$U \le n$)。

  • 内层 while 循环: 只有当元素是序列的起点时才会触发。对于任何一个数字,它要么是起点而被移入 while 循环进行后续递增遍历,要么是中间项直接被 if 语句跳过。

  • 总遍历次数: 每一个数字在整个算法生命周期中,最多只会在外层循环被访问一次,在内层 while 循环中被访问一次。因此,所有元素被访问的累加次数不会超过 $2n$ 次。

  • 结论: 算法的整体时间复杂度为稳定且线性的 $O(n)$。

2. 空间复杂度:$O(n)$

  • 空间消耗源: 算法显式地创建了一个 HashSet 来存储输入数组中的元素。

  • 消耗量级: 在最坏情况下(数组中所有元素均不重复),HashSet 需要存储全部 $n$ 个元素。

  • 结论: 算法的空间复杂度为 $O(n)$。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值