js.128最长连续序列

链接:128. 最长连续序列 - 力扣(LeetCode)

题目:

给定一个未排序的整数数组 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 <= 105
  • -109 <= nums[i] <= 109

思路:

用map记录遍历过的连续序列区间,因为用数组或者对象的话,比较的是引用地址,所以我使用字符串在标记左右数字。用“1,“开头代表为区间左节点,”2,“代表区间右节点。对应的value值为最长序列长度。用set记录已经计算过的数字,防止重复计算。

遍历nums数组,对于每一个数字,有四种情况。

1,该数字的左边和右边都有区间,将两个区间和该数字合并,删除左区间的右节点和右区间的左节点,改变最长序列长度。

2,该数字在一个区间的右边,将原区间的右节点删去,该数子变成右节点,改变最长序列长度。

3,该数字在一个区间的左边,将原区间的左节点删去,该数字变成左节点,改变最长序列长度。

4,该数字的左边和右边都没有区间,将该数字加入map集合中,左节点和右节点都是自己,序列长度为1。

代码:

/**
 * @param {number[]} nums
 * @return {number}
 */
var longestConsecutive = function(nums) {
    let set = new Set(),map = new Map(),max = 0
    for(let i = 0 ; i<nums.length ; i++ ){
        if(set.has(nums[i])) continue
        let len = 1
        // 第一种情况
        if(map.has('1,'+(nums[i]+1))&&map.has('2,'+(nums[i]-1))){
            let leftlen = map.get('2,'+(nums[i]-1)),rightlen = map.get('1,'+(nums[i]+1))
            len = leftlen+rightlen+1
            map.set('1,'+(nums[i]-leftlen),len)
            map.set('2,'+(nums[i]+rightlen),len)
            map.delete('1,'+(nums[i]+1))
            map.delete('2,'+(nums[i]-1))
        }else if(map.has('1,'+(nums[i]+1))){
            // 第二种情况
            len = map.get('1,'+(nums[i]+1))+1
            map.set('1,'+nums[i],len)
            map.delete('1,'+(nums[i]+1))
            map.set('2,'+(nums[i]+len-1),len)
        }else if(map.has('2,'+(nums[i]-1))){
            // 第三种情况
            len = map.get('2,'+(nums[i]-1))+1
            map.set('2,'+nums[i],len)
            map.delete('2,'+(nums[i]-1))
            map.set('1,'+(nums[i]-len+1),len)
        }else{
            // 第四种情况
            map.set('1,'+nums[i],1)
            map.set('2,'+nums[i],1)
        }
        max = len>max?len:max
        set.add(nums[i])
    }
    return max
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值