LeetCode 128. 最长连续序列:O (n) 时间的哈希集合 + 剪枝解法全解析

  1. 最长连续序列

一、题目

给定一个未排序的整数数组 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)

二、思路

因为本题有时间复杂度O(n)的要求,所以不能排序(排序的时间复杂度至少为 O(n log n)

于是通过「哈希集合」实现快速查找,并通过「剪枝」避免重复遍历。
核心思路:

是对于nums中的元素x,先判断x-1是否在数组中,来找到起点,以此时的x为起点,判断x+1,x+2 ...是否在数组中。
关键观察:

一个连续序列的「起点」满足:x-1 不存在于数组中(比如序列 [1,2,3,4] 的起点是 1,因为 0 不在数组中)。

  • 若 x-1 存在,则 x 不是起点,无需遍历以 x 为起点的连续序列(避免重复计算);
  • 若 x-1 不存在,则 x 是起点,需遍历 x+1、x+2... 直到不存在,统计序列长度。

为了满足时间复杂度的要求,一定要做的两个优化

1)使用set集合(哈希集合 ),可以以O(1)的时间复杂度来判断数字是否在nums中。

2)找到最开始的x起点,这样其他的点将不进入内部循环

还可以进行剪枝优化

如果现在得到的最长连续序列的长度已经超过了数组长度的一半,则可以break了,因为假如一共10个数,现在的最长已经是6,则后面的总共才4个,就算这4个全部连续,也没有6大,所以没有必要再进行运算。

三、代码

javascript 复制代码
/**
 * @param {number[]} nums
 * @return {number}
 */
var longestConsecutive = function(nums) {
    //转为set去重,实现O(1)查找,同时处理空数组/重复元素场景。
    const st = new Set(nums);
    let ans = 0;
    //遍历去重后的每个元素
    for(const x of st){
        //若x-1存在,则x不是起点,跳过,避免重复遍历,增加时间复杂度
        if(st.has(x-1)){
            continue;
        }
        //此时x是起点,统计连续序列长度
        let y = x+1;
        //使用while遍历,直到连续序列中断
        while(st.has(y)){
            y++;
        }
        //在不连续的数组中和往期的ans打擂台,如[1,2,3,4]和[100,101]
        ans=Math.max(ans,y-x);
        //剪枝优化:当前最长长度已经超过去重后数组长度的一半,剩下的就算全部连续也不可能比现在的最长序列长度长,无需继续遍历
        if(ans*2>=st.size){
            break;
        }
    }
    return ans;
};

四、复杂度

时间复杂度:O(n) ,其中 n 是 nums 的长度。在二重循环中,每个元素至多遍历两次:在外层循环中遍历一次,在内层循环中遍历一次(相加为2n)。所以二重循环的时间复杂度是 O(n) 的。比如 nums=[1,2,3,4],其中 2,3,4 不会进入内层循环,只有 1 会进入内层循环。所以它们不是相乘的关系,而是相加的关系
空间复杂度:O(m)。其中 m 是 nums 中的不同元素个数。

相关推荐
木卫二号Coding5 小时前
Docker-构建自己的Web-Linux系统-Ubuntu:22.04
linux·前端·docker
CHU7290356 小时前
一番赏盲盒抽卡机小程序:解锁惊喜体验与社交乐趣的多元功能设计
前端·小程序·php
RFCEO6 小时前
前端编程 课程十二、:CSS 基础应用 Flex 布局
前端·css·flex 布局·css3原生自带的布局模块·flexible box·弹性盒布局·垂直居中困难
天若有情6736 小时前
XiangJsonCraft v1.2.0重大更新解读:本地配置优先+全量容错,JSON解耦开发体验再升级
前端·javascript·npm·json·xiangjsoncraft
2501_944525547 小时前
Flutter for OpenHarmony 个人理财管理App实战 - 预算详情页面
android·开发语言·前端·javascript·flutter·ecmascript
打小就很皮...7 小时前
《在 React/Vue 项目中引入 Supademo 实现交互式新手指引》
前端·supademo·新手指引
C澒7 小时前
系统初始化成功率下降排查实践
前端·安全·运维开发
只是懒得想了7 小时前
C++实现密码破解工具:从MD5暴力破解到现代哈希安全实践
c++·算法·安全·哈希算法
C澒7 小时前
面单打印服务的监控检查事项
前端·后端·安全·运维开发·交通物流
pas1367 小时前
39-mini-vue 实现解析 text 功能
前端·javascript·vue.js