128.最长连续序列
要再O(n)时间复杂度内找到最长连续数字序列,核心思路是:
1、先用哈希集合unordered_set存储数组所有元素,利用集合的O(1)查找特性;直接在原数组中查找元素的时间复杂度是 O(n),而哈希集合(unordered_set)的查找时间复杂度是 O(1)(平均情况)。这一点点差异,会让整个算法的时间复杂度发生质的变化。
2、遍历每个元素(for循环),仅当该元素是连续序列的起点(即当num-1不在集合中)时(if条件判断),才向后查找连续数组(while循环),统计序列长度;
3、全程记录最长序列的长度;
这种方式能保证每个元素最多被访问2次(一次遍历,一次作为连续序列被查找)整体时间复杂度为O(n)。
完整代码实现:
#include
#include
#include <unordered_set>
using namespace std;
int longestConsecutive(vector
// 1. 将数组元素存入无序集合,去重且支持O(1)查找
unordered_set<int> num_set(nums.begin(), nums.end());
int max_length = 0; // 记录最长连续序列长度
// 2. 遍历集合中的每个元素
for (int num : num_set) {
// 仅当num是连续序列的起点(num-1不存在)时,才开始统计
if (num_set.find(num - 1) == num_set.end()) {
int current_num = num;
int current_length = 1; // 当前连续序列长度
// 3. 向后查找连续数字,统计长度
while (num_set.find(current_num + 1) != num_set.end()) {
current_num++;
current_length++;
}
// 4. 更新最长长度
max_length = max(max_length, current_length);
}
}
return max_length;
}
// 测试用例
int main() {
// 示例1:常规情况
vector<int> nums1 = {100, 4, 200, 1, 3, 2};
cout << "最长连续序列长度:" << longestConsecutive(nums1) << endl; // 输出4(序列1,2,3,4)
// 示例2:空数组
vector<int> nums2 = {};
cout << "最长连续序列长度:" << longestConsecutive(nums2) << endl; // 输出0
// 示例3:单元素数组
vector<int> nums3 = {5};
cout << "最长连续序列长度:" << longestConsecutive(nums3) << endl; // 输出1
// 示例4:重复元素+连续序列
vector<int> nums4 = {0, 3, 7, 2, 5, 8, 4, 6, 0, 1};
cout << "最长连续序列长度:" << longestConsecutive(nums4) << endl; // 输出9(0-8)
return 0;
}
代码关键部分解释:
1、哈希集合初始化:unordered_set
将数组元素存入集合,自动去重,且后续查找操作的时间复杂度为 O (1)。
2、判断序列起点:if (num_set.find(num - 1) == num_set.end())
只有当 num-1 不在集合中时,num 才是连续序列的第一个元素,避免重复统计(比如遍历到 2 时,若 1 存在,就不需要再从 2 开始统计,因为从 1 开始已经统计过了)。
具体代码解释:
if (num_set.find(num - 1) == num_set.end())
| 代码片段 | 含义 |
|---|---|
| num_set | 存储数组所有元素的哈希集合(unordered_set) |
| num_set.find(num - 1) | 在集合中查找 num-1 这个数字:- 如果找到,返回指向该元素的迭代器;- 如果没找到,返回 num_set.end()(集合的 “末尾” 迭代器,代表 “没找到”) |
| == num_set.end() | 判断 “查找结果” 是否等于 “末尾迭代器”,即:是否没找到 num-1 |
unordered_set
| 部分 | 含义 |
|---|---|
| unordered_set |
声明一个存储 int 类型元素的无序哈希集合(STL 容器);unordered_set 是 C++ STL 提供的哈希集合容器,底层基于哈希表实现。 |
| num_set | 你定义的这个哈希集合的变量名。 |
| (nums.begin(), nums.end()) | 传给 unordered_set 构造函数的参数,是一对 “迭代器”:- nums.begin():指向数组 nums 第一个元素的迭代器;- nums.end():指向数组 nums 最后一个元素下一个位置的迭代器;这对迭代器共同表示 “数组 nums 的所有元素范围”。 |
核心原理:范围构造函数
unordered_set 提供了多种构造函数,这里用到的是范围构造函数(Range Constructor),其作用是:
遍历传入的迭代器范围([begin, end)),把范围内的所有元素依次插入到 unordered_set 中,同时自动去重(因为集合不允许重复元素)
num_set(unordered_set)能自动去重,核心原因是:集合(Set)这种数据结构的本质特性 —— 不允许存储重复元素,这是 C++ STL 中 unordered_set 的设计规则,和底层实现逻辑紧密相关
浙公网安备 33010602011771号