题目描述
给定一个未排序的整数数组 nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n)
的算法解决此问题。
示例 1:
ini
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
示例 2:
ini
输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9
思路
首先将数组元素都添加到set中,借助set高效的查找
再对数组元素进行遍历,找到连续序列的起点或终点,这样可以减少不必要的操作,因为从起点(连续序列中的最小数字)向上遍历或者从终点向下遍历能确定当前连续序列的最大长度
复杂度分析
时间复杂度
1. 创建 Set
- 操作 :遍历数组
nums
并将每个元素添加到Set
中。 - 时间复杂度 :O(N),其中 N 是数组
nums
的长度。
2. 遍历 Set
并查找最长连续序列
- 外层循环 :遍历
Set
中的每个元素,时间复杂度为 O(N)。 - 内层循环 :
- 只有在当前数字
n
是某个序列的起始点(即n - 1
不在Set
中)时,才会进入内层while
循环。 - 每个数字最多只会被访问一次,无论是作为外层循环的一部分还是在内层循环中被递增处理。
- 因此,内层循环总的操作次数不会超过 N 次。
- 只有在当前数字
- 总时间复杂度 :
- 外层循环:O(N)
- 内层循环:O(N)(由于每个数字最多被处理一次)
- 综合总时间复杂度:O(N) + O(N) = O(N)
空间复杂度
Set
:存储了数组nums
中的所有唯一元素,空间复杂度为 O(N)。- 其他变量 :
maxLen
和curLen
:常数空间,O(1)。
- 总空间复杂度 :O(N)
为什么时间复杂度是 O(N) 而不是 O(N²):
- 虽然有两层循环,但内层循环的次数是由外层条件控制的,即只有在找到序列的起始点时才会执行。
- 每个元素最多只会被检查一次。在内层循环中,
n
会被递增,并且这些递增操作不会重叠或重复处理相同的元素。
code
javascript
/**
* @param {number[]} nums
* @return {number}
*/
var longestConsecutive = function(nums) {
const set = new Set()
for(let n of nums){
set.add(n)
}
let maxLen = 0
for(let n of set.values()){
let curLen = 1
if(!set.has(n - 1)){
while(set.has(n + 1)){
n++
curLen++
}
}
maxLen = Math.max(maxLen, curLen)
}
return maxLen
};