给定一个未排序的整数数组 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
提示:
0 <= nums.length <= 104
-109 <= nums[i] <= 109
思路:
一开始用的是排序算法,虽然因为有内部优化所以时间不错,但是没有达到题目要求的O(n)。
代码:
/**
* @param {number[]} nums
* @return {number}
*/
var longestConsecutive = function(nums) {
if(nums.length==0) return 0;
let arr = nums.sort((a,b)=>{return a-b});
let sum =1;
let ans=0;
for(let i =0;i<arr.length-1;i++) {
if(arr[i]===arr[i+1]) continue;//如果相同,就跳过
if(arr[i]+1===arr[i+1]) sum++;
else {
ans=Math.max(ans,sum);
sum=1;
}
}
ans=Math.max(ans,sum);
return ans;
};
思路:如果要时间复杂度达到要求,可以用哈希表map或者用set。
map的思路关键是value存什么。建议看这个大佬的题解:
力扣题解Map和Set
map代码如下:
/**
* @param {number[]} nums
* @return {number}
*/
var longestConsecutive = function(nums) {
let map =new Map();
let max = 0;
for(let i = 0; i < nums.length; i++) {
if(!map.has(nums[i])) {
let leftlen = map.get(nums[i]-1)||0;
let rightlen = map.get(nums[i]+1)||0;
let len = leftlen+1+rightlen;
max = Math.max(max,len);
map.set(nums[i],len);
map.set(nums[i]-leftlen,len);
map.set(nums[i]+rightlen,len);
}
}
return max;
};
最好用的我觉得是set
代码:
var longestConsecutive = (nums) => {
const set = new Set(nums) // set存放数组的全部数字
let max = 0
for (let i = 0; i < nums.length; i++) {
if (!set.has(nums[i] - 1)) { // nums[i]没有左邻居,是序列的起点
let cur = nums[i]
let count = 1
while (set.has(cur + 1)) { // cur有右邻居cur+1
cur++ // 更新cur
count++
}
max = Math.max(max, count) // cur不再有右邻居,检查count是否最大
}
}
return max
}