题目:
给定一个未排序的整数数组
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
};