1.题目如下:
2.思路:
可以使用暴力枚举,将数组中的每一个数都当作起始序列,然后再去让这个数+1,直到+1的数不存在为止。但是这种做法的时间复杂度过高,因为并不是所有的数都需要被当作起始序列去遍历,比如说:上图数组[100,4,200,1,3,2]中2,3,4均不需要当作起始序列去遍历,因为有1存在,所以我们可以考虑对于数组中的每一个数num,在遍历后首先判断是否存在num-1这个数,如果存在,说明这个数不能当作起始序列,如果不存在,说明这个数可以当作起始序列。比如:[100,4,200,1,3,2]中100-1=99,然后数组中不存在99,说明100可以作为起始序列,又比如4-1=3,数组中存在3,说明4不可以作为起始序列。详见下图:
在此基础上,还要特别说明一点,如果数组中存在重复元素也会增加时间复杂度,所以对数组操作时应该首先对数组“去重”
具体代码如下:
var longestConsecutive = function(nums) {
let numSet = new Set(nums);
let longestStreak = 0;
for( let num of numSet){
if(!numSet.has(num-1)){//如果不存在比自身小1的数,那么此时的num即可作为开始序列
let currentNum = num;
let currentStreak = 1;
while(numSet.has(currentNum+1)){//查找连续的数,直到num+1不存在为止
currentNum+=1;//这里的while循环应该嵌套在if语句中,否则会接收不到定义的变量
currentStreak+=1;//并且从逻辑上来讲,我们需要找到一个数的开始序列才会去找它的连续的数
}
longestStreak = Math.max(longestStreak, currentStreak);//返回最长序列
}
}
return longestStreak;
}
写这个代码有几个细节要注意:
1.首先是JavaScript中的Set对象,这个对象类似数组,但是可以自动去重
2.而且Set对象没有.length属性,遍历时只能采用for......each或者for( xxx of xxxx)
3.if判断条件中不能写成if(!numSet[i]-1)
4.while循环中,不要把while (numSet.has(currentNum + 1)这里写成while (numSet.has(num + 1)
这俩有着本质区别,我第一次写时,显示时间复杂度过高就是没注意这个!
currentNum + 1代表着从num那里传递过来的数值+1
而num + 1代表着numSet数组中,位于num后一位的元素