题目描述
一开始低估了这道题,想的是空间换时间,正数负数各建一个数组,一个倒着遍历、一个正着遍历,最后取最大值,代码如下:
/**
* @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;
};
只通过了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;
};
提交结果如下:
题目要求时间复杂度为O(n),这个代码也只存在一个for循环,定义的map存储的是区间长度就是一个Number,但最后时间与内存的效果并不太理想,暂时也想不到进一步优化的空间了