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 中的不同元素个数。

相关推荐
鹏多多11 小时前
移动端H5项目,还需要react-fastclick解决300ms点击延迟吗?
前端·javascript·react.js
serioyaoyao11 小时前
上万级文件一起可视化,怎么办?答案是基于 ParaView 的远程可视化
前端
万少11 小时前
端云一体 一天开发的元服务-奇趣故事匣经验分享
前端·ai编程·harmonyos
WindrunnerMax11 小时前
从零实现富文本编辑器#11-Immutable状态维护与增量渲染
前端·架构·前端框架
@––––––11 小时前
力扣hot100—系列4-贪心算法
算法·leetcode·贪心算法
不想秃头的程序员11 小时前
Vue3 封装 Axios 实战:从基础到生产级,新手也能秒上手
前端·javascript·面试
数研小生11 小时前
亚马逊商品列表API详解
前端·数据库·python·pandas
你听得到1111 小时前
我彻底搞懂了 SSE,原来流式响应效果还能这么玩的?(附 JS/Dart 双端实战)
前端·面试·github
不倒翁玩偶11 小时前
npm : 无法将“npm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。
前端·npm·node.js