题目
给定一个未排序的非负整型数组,找出数字连续的最长序列的长度。要求时间复杂度 O(n)
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
原题链接:https://leetcode-cn.com/problems/longest-consecutive-sequence/
思路
思路1
哈希法
首先暴力法就是,外循环遍历每一个数,设这个数为 x,然后进一步查找数组当中有没有 x + 1、 x + 2,但这样每一次查找都是 O(n),有没有办法把查找降为 O(1) ?答案是肯定的,我们维护一个哈希表即可。
即先把所有数放入哈希表中,外循环遍历每一个数 x,然后到哈希表当中找是否有 x + 1,有的话再进一步找 x + 2。知道 找不到 x + n 为止,此时 n 就是最大长度了。
另外外循环可能存在重复的情况,如第一次遇到 a,我们会到哈希表中找 a+1、a+2、a+3…;第二次遇到 a+1 时,我们会到哈希表中找 a+2、a+3…;实际上,第二次这个查找是多余的,即从非序列首个数字开始的遍历都是多余的。我们可以通过判断 x - 1 是否在哈希表来判断 x 是否是序列首个数字,由此跳过一次查找。
这样也就使得我们的复杂度降为 O(n)。
- 复杂度分析
- 时间复杂度 O(n)。
- 空间复杂度 O(n)。哈希表
思路2
排序法
另一种就是对数组先进行一次排序,然后再采用双指针法记录窗口大小即可。但是时间复杂度比 思路1 大一些,空间复杂度可以省一点。由于时间复杂度不满足题目要求,这里先不展开写code了。
- 复杂度分析
- 时间复杂度 O(nlogn)。
- 空间复杂度 O(1)。
代码
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_set<int> num_set;
for (int num: nums) {
num_set.insert(num);
}
int max_length = 0;
for (int num: nums) {
if (num_set.count(num - 1) == 0) {
int cur_length = 1;
int next_num = num + 1;
while(num_set.count(next_num)) {
cur_length++;
next_num++;
}
max_length = max(max_length, cur_length);
}
}
return max_length;
}
};