1.最长连续序列
题目:
给定一个未排序的整数数组 nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n)
的算法解决此问题。
示例 1:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
示例 2:
输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9
示例 3:
输入:nums = [1,0,1,2]
输出:3
提示:
0 <= nums.length <= 105
-109 <= nums[i] <= 109
解题过程
思路
这道题要求找出一个未排序的整数数组中最长的连续数字序列的长度,而且要求时间复杂度为 O(n)。这意味着我们不能使用像排序这样的时间复杂度为 O(n log n) 的操作。那该怎么解决这个问题呢?
一种有效的方法是利用哈希集合(unordered_set
在 C++ 中)。哈希集合允许我们在常数时间内检查某个元素是否存在。
具体来说,我们可以这样操作:
- 将数组中的元素存入哈希集合:这样我们可以快速检查某个数字是否存在。
- 遍历数组中的每个元素:
-
- 如果当前元素是某个连续序列的最小值(即
num - 1
不在哈希集合中),就尝试从这个元素开始,向后查找连续的数字,并记录连续的长度。
- 如果当前元素是某个连续序列的最小值(即
- 记录最长的连续序列长度:在遍历过程中不断更新最长长度。
这样做的原因是,如果我们从每个可能的序列起点开始查找,就可以避免重复计算。例如,如果 1
不在哈希集合中,那么我们不会从 2
开始查找,因为序列 [2,3,4]
必然包含在以 1
为起点的序列 [1,2,3,4]
中。
代码:
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_set<int> num_set(nums.begin(), nums.end());
int longest_streak = 0;
for (int num : nums) {
if (!num_set.count(num - 1)) { // 如果当前 num 是一个序列的最小值
int current_num = num;
int current_streak = 1;
while (num_set.count(current_num + 1)) {
current_num += 1;
current_streak += 1;
}
longest_streak = max(longest_streak, current_streak);
}
}
return longest_streak;
}
};
代码解释
- 哈希集合初始化 :
unordered_set<int> num_set(nums.begin(), nums.end());
将数组中的元素存入哈希集合,方便快速查找。 - 遍历数组 :对于每个元素
num
,检查num - 1
是否存在。如果不存在,说明num
可能是一个连续序列的起点。 - 查找连续数字 :从
num
开始,依次查找num + 1
,num + 2
, 直到找不到为止,记录连续的长度。 - 更新最长长度:在查找过程中,不断更新记录的最长连续序列长度。
这种方法确保每个数字最多被访问两次(一次作为起点,另一次作为序列的一部分),所以总时间复杂度是 O(n)。