刷算法——最长连续序列

49 阅读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

Set查找

/**
 * @param {number[]} nums
 * @return {number}
 */
var longestConsecutive = function(nums) {
    const numSet= new Set(nums)
    let maxLength=0
    for(let num of nums){
        if(!numSet.has(num-1)){
            let current=num
            let length=1
            while(numSet.has(current+1)){
                current++
                length++
            }
            maxLength = Math.max(maxLength,length)
        }
    
    }
    return maxLength
}
  • Set 操作虽然理论 O(1),但哈希冲突、扩容等因素会增加常数时间;

  • 如果数字范围非常大(比如几百万,几千万),单次 while 循环会产生大量连续查询,CPU 缓存和内存访问效率降低。使用这个方法LeeCode不通过,会给超时警告。 image.png

哈希表+动态区间

/**
 * @param {number[]} nums
 * @return {number}
 */
/**
 * @param {number[]} nums
 * @return {number}
 */
var longestConsecutive = function(nums) {
    let map=new Map(),maxCount=0

    for (let num of nums) {
        if (!map.has(num)) {
            const leftLen = map.get(num - 1) || 0;
            const rightLen = map.get(num + 1) || 0;

            const curLen = leftLen + 1 + rightLen;

            map.set(num, curLen);
            // 更新左边界
            map.set(num - leftLen, curLen);
            // 更新右边界
            map.set(num + rightLen, curLen);

            maxCount = Math.max(maxCount, curLen);
        }
    }
    return maxCount
}