力扣热题---最长连续序列

42 阅读2分钟

题目描述

image.png

一开始低估了这道题,想的是空间换时间,正数负数各建一个数组,一个倒着遍历、一个正着遍历,最后取最大值,代码如下:

/**
 * @param {number[]} nums
 * @return {number}
 */
var longestConsecutive = function (nums) {
    // 思路:空间换时间,将数组元素按其数值大小存在在临时数组上,通过遍历临时数组来找最大长度
    let posArr = [], negArr = [], max = 0, j = 0;
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] >= 0) posArr[nums[i]] = 1;
        if (nums[i] < 0) negArr[-nums[i]] = 1;
    }
    for (let i = negArr.length - 1; i > 0; i--) {
        if (negArr[i]) {
            j++;
            if (j > max) max = j;
        } else
            j = 0
    }
    for (let i = 0; i < posArr.length; i++) {
        if (posArr[i]) {
            j++;
            if (j > max) max = j;
        } else
            j = 0
    }
    return max;
};

image.png

只通过了67个用例,数字到亿级别就要超时。数字太大了就不能遍历,只能考虑哈希表的方法,思想如下:

  • 用哈希表维护连续长度,每个连续区间两端记录该连续区间长度,若存在区间合并则更新新区间两端的长度
  • 遍历数组,若节点已经在哈希表存在则不处理
  • 若为新节点,则取节点两侧所记录的长度值进行合并,并取合并之后新区间两端的值进行合并
  • 返回最大的长度值 代码如下:
 * @param {number[]} nums
 * @return {number}
 */
var longestConsecutive = function (nums) {
    let map = new Object(), max = 0;
    for (let i = 0; i < nums.length; i++) {
        if(!map[nums[i]]){
          let left = map[nums[i] - 1] || 0;
          let right = map[nums[i] + 1] || 0;
          let curLength = left + right + 1;
          if(curLength > max) max = curLength;
          map[nums[i]] = curLength;
          map[nums[i] - left] = curLength;
          map[nums[i] + right] = curLength
        }
    }
    return max;
};

提交结果如下:

image.png 题目要求时间复杂度为O(n),这个代码也只存在一个for循环,定义的map存储的是区间长度就是一个Number,但最后时间与内存的效果并不太理想,暂时也想不到进一步优化的空间了