最近刚开始刷hot100,记录一下自己刷题的过程和复习到的知识点
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) **的算法解决此问题。
示例 1:
输入: nums = [100,4,200,1,3,2]
输出: 4
解释: 最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
示例 2:
输入: nums = [9,1,4,7,3,-1,0,5,8,-1,6]
解释:3,4,5,6,7,8,9
输出: 7
示例 3:
输入: nums = [1,0,-1]
解释:-1,0,1
输出: 3
示例 4:
输入: nums = []
输出: 0
还有一个示例是1-10w的顺序打乱数组 这几个是我认为比较有特点的例子
思路: 1.首先他是需要提取出这个无序数组里的连续的序列,如果中间中断,就需要重新寻找。 所以我先声明一个数组bestCount存储过程中产生的连续序列长度,输出的时候对这个数组求max值。取最大值的方法我是参考的这篇文章blog.csdn.net/xiansibao/a…
2.对于空数组,使用let count = nums.length === 0 ? 0 : 1;检查。由于复杂度需要O(n),不能用暴力枚举法。所以 是否存在连续序列,首先用sort和set方法排序和去重,然后用数组的includes()方法对遍历到的当前元素来判定,如果存在该元素+1的就说明有序列,然后计数值+1,否则将当前的计数值加入bestCount,然后count置为1.关于遍历的方法我参考的是这篇文章
3.然而当我遇见了示例5,却报错说超时,猜测可能是因为使用的数组,遍历和排序效率不够好。所以就改用哈希表。js中是没有哈希表的,但是哈希表的实现和对象类似,即采用键值对的形式无序存储。而且哈希表的查找效率
使用myArray.forEach(element => { hashMap.set(element, "some value"); });
转为哈希表之后,就顺便去重也免去排序了,对于哈希表中的下一个存在,parseInt(key) + 1 in hashMap检测,这样执行速度大大提升。
4.但是我碰到示例4后又出错,1,0,-1无论如何只取得count==2。查询资料得知这是因为在 JavaScript 中,对象的属性是无序的。即使你在数组中先排序了,转换回哈希表(对象)时,属性的顺序不一定会保持排序的顺序。因为对象的属性排序在 ECMAScript 规范中并没有被定义。,说明还是需要排序。查询资料得知map与哈希表类似,但是map可以按添加键值对的顺序。- Map 还提供了一些额外的功能,例如有序的键值对、更灵活的键类型(可以是任意数据类型,包括对象),并且键值对的顺序是插入顺序。
遍历 Map 可以使用 forEach 方法或迭代器(for...of)。
5.改为map数据结构之后,最后终于运行出来了,附上源码
var longestConsecutive = function (nums) {
let count = nums.length === 0 ? 0 : 1;
let bestCount = [0];
const mapObj = new Map();
nums.sort((a, b) => a - b);
nums.forEach((element) => {
mapObj.set(element, element);
});
for (let key of mapObj.keys()) {
if (mapObj.has(key + 1)) {
count++;
} else {
bestCount.push(count);
count = 1;
}
}
bestCount.push(count);
console.log(mapObj);
return Math.max(...bestCount);
};
console.log(longestConsecutive([0, 1, -1]));