题目描述:
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度
输入:nums = [100,4,200,1,3,2] 输出:4 解释:最长数字连续序列是[1, 2, 3, 4]。它的长度为 4。
解题思路:
- 首先想到的是动态规划,这种计算最长递增子序列。
- 然后发现是用哈希表来实现。
解法一:动态规划
// 动态规划算法
// 放到集合里去重
const arraySet = new Set(nums);
// 把去重以后的集合转成数组并升序排序
const arraySort = Array.from(arraySet).sort((a, b) => a - b);
// 记录长度
let dp = [1];
if (!nums.length) {
return 0;
}
for (let i = 1; i < arraySort.length; i++) {
// 从第二个开始,如果连续则记录当前是连续的第几个数字
if (arraySort[i - 1] + 1 === arraySort[i]) {
dp[i] = dp[i - 1] + 1;
} else {
// 如果一旦断开,就从1开始重新开始
dp[i] = 1;
}
}
// 返回最长的长度
return Math.max(...dp);
用时:
Your runtime beats 45.87 % of typescript submissions
Your memory usage beats 23.56 % of typescript submissions (66.6 MB)
解法二:集合
这个方法一开始我没注意用的是for循环遍历数组一样的写法,就是上面的写法,计算运行的速度很慢,然后我和答案去比较为什么这么慢,发现这里是直接for of 遍历集合的。
// 放到集合里去重
let numsSet = new Set(nums);
// 记录最长的连续的长度
let maxLengthArray = 0;
// 遍历集合,这里一开始写错了,用数组的遍历方式,效率极低
for (const num of numsSet) {
// 先从边界开始找,如果这个数没有人在它左边(比他小1),说明可以以他为起点,找比他大的数字
if (!numsSet.has(num - 1)) {
// 记录开始的数字和长度
let curNum = num;
let maxLength = 1;
// 找比他大1的数字
while (numsSet.has(curNum + 1)) {
// 记录每次的数字
curNum = curNum + 1;
// 记录长度
maxLength++;
}
// 和之前记录的长度比较留一个最大的
maxLengthArray = Math.max(maxLengthArray, maxLength);
}
}
return maxLengthArray;
用时:
时间104 ms 击败 79.34% 内存61.9 MB 击败 43.39%