标题:最长连续序列
出处:128. 最长连续序列
6 级
给定一个未排序的整数数组 nums \texttt{nums} nums,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) \texttt{O(n)} O(n) 的算法解决此问题。
示例 1:
输入: nums = [100,4,200,1,3,2] \texttt{nums = [100,4,200,1,3,2]} nums = [100,4,200,1,3,2]
输出: 4 \texttt{4} 4
解释:最长数字连续序列是 [1, 2, 3, 4] \texttt{[1, 2, 3, 4]} [1, 2, 3, 4]。它的长度为 4 \texttt{4} 4。
示例 2:
输入: nums = [0,3,7,2,5,8,4,6,0,1] \texttt{nums = [0,3,7,2,5,8,4,6,0,1]} nums = [0,3,7,2,5,8,4,6,0,1]
输出: 9 \texttt{9} 9
为了寻找最长连续序列,对于数组 nums \textit{nums} nums 中的元素 num \textit{num} num,需要找到最大的正整数 k k k,使得从 num \textit{num} num 到 num + k − 1 \textit{num} + k - 1 num+k−1 都在数组中,则从 num \textit{num} num 开始的最长连续序列的长度是 k k k。
为了判断一个元素是否在数组中,可以使用哈希集合存储数组中的元素,判断一个元素是否在哈希集合中的时间复杂度是 O ( 1 ) O(1) O(1)。假设数组 nums \textit{nums} nums 的长度是 n n n,如果对数组中的每个元素都进行上述操作,则对于一个元素计算从该元素开始的最长连续序列的长度需要 O ( n ) O(n) O(n) 的时间,总时间复杂度是 O ( n 2 ) O(n^2) O(n2)。
为了将时间复杂度降低到 O ( n ) O(n) O(n),必须进一步优化。对于数组 nums \textit{nums} nums 中的元素 num \textit{num} num,如果 num − 1 \textit{num} - 1 num−1 也在数组中,则将 num − 1 \textit{num} - 1 num−1 添加到 num \textit{num} num 的前面可以使得连续序列的长度加 1 1 1,因此从 num − 1 \textit{num} - 1 num−1 开始的最长连续序列的长度一定大于从 num \textit{num} num 开始的最长连续序列的长度。基于该结论,对于数组 nums \textit{nums} nums 中的元素 num \textit{num} num,只有当 num − 1 \textit{num} - 1 num−1 不在数组中时,才需要计算从 num \textit{num} num 开始的最长连续序列的长度。
将数组 nums \textit{nums} nums 中的元素都加入哈希集合之后,遍历哈希集合,对于每个元素 num \textit{num} num,如果 num − 1 \textit{num} - 1 num−1 在哈希集合中则跳过 num \textit{num} num,如果 num − 1 \textit{num} - 1 num−1 不在哈希集合中则计算从 num \textit{num} num 开始的最长连续序列的长度,具体做法如下:
用 maxNum \textit{maxNum} maxNum 表示从 num \textit{num} num 开始的最长连续序列的最大元素,初始时 maxNum = num \textit{maxNum} = \textit{num} maxNum=num,如果 maxNum + 1 \textit{maxNum} + 1 maxNum+1 在哈希集合中则将 maxNum \textit{maxNum} maxNum 的值加 1 1 1,重复增加 maxNum \textit{maxNum} maxNum 的值,直到 maxNum + 1 \textit{maxNum} + 1 maxNum+1 不在哈希集合中;
从 num \textit{num} num 开始的最长连续序列的长度是 maxNum − num + 1 \textit{maxNum} - \textit{num} + 1 maxNum−num+1,用该长度更新整个数组的最长连续序列的长度。
遍历结束之后,即可得到整个数组的最长连续序列的长度。
优化后的做法中,由于不可能作为最长连续序列的第一个数的元素会跳过,因此哈希集合中的每个元素只会被遍历一次,时间复杂度是 O ( n ) O(n) O(n)。
class Solution {
public int longestConsecutive(int[] nums) {
Set<Integer> set = new HashSet<Integer>();
for (int num : nums) {
set.add(num);
}
int maxLength = 0;
for (int num : set) {
if (set.contains(num - 1)) {
continue;
}
int maxNum = num;
while (set.contains(maxNum + 1)) {
maxNum++;
}
maxLength = Math.max(maxLength, maxNum - num + 1);
}
return maxLength;
}
}
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。遍历数组 nums \textit{nums} nums 并将全部元素加入哈希集合需要 O ( n ) O(n) O(n) 的时间,遍历哈希集合计算最长连续序列的长度时,由于不可能作为最长连续序列的第一个数的元素会跳过,因此哈希集合中的每个元素只会被遍历一次,时间复杂度是 O ( n ) O(n) O(n)。
空间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。需要使用哈希集合存储数组 nums \textit{nums} nums 中的元素,哈希集合中的元素个数不会超过 n n n。