一、题目回顾
LeetCode 128「最长连续序列」要求我们在一个未排序的整数数组 nums 里,找出最长的连续数字片段,返回它的长度。题目还额外卡了一个条件:算法时间复杂度要做到 O(n)。
两个例子一看就明白:
nums = [100,4,200,1,3,2],答案是4,连续序列是[1,2,3,4];nums = [0,3,7,2,5,8,4,6,0,1],答案是9,完整连续序列是0-8。
这里最先要排除的就是排序。排序当然能做,但时间复杂度是 O(nlogn),题目不认这个解法。
二、思路:先找起点,再向后扩
这题真正省事的地方,在于不用从每个数都往后数一遍。我们把所有数字扔进一个哈希集合里,查找某个数在不在里面就很快。
接下来只做一件事:判断一个数是不是'连续段的起点'。判断标准也简单,x - 1 不在集合里,x 才可能是起点。因为如果前一个数还在,那 x 只是中间那个,不值得再算一遍。
流程可以压成三步:
- 把数组元素放进
unordered_set,去重顺手就做了; - 遍历集合里的每个数
x,如果x - 1存在,就跳过; - 只有当
x是起点时,才从x + 1开始一路向后查,直到断开为止。
这样做的好处很直接:每个数最多被处理一次,重复的扩展都被砍掉了。这个题的 O(n) 主要就是靠这个细节撑起来的。
三、C++ 代码
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
// 1. 将数组元素存入哈希集合(去重 + 快速查找)
unordered_set<int> hash(nums.begin(), nums.end());
int len = 0; // 记录最长序列长度
// 2. 遍历集合中的每个数
for (int x : hash) {
// 3. 仅当 x-1 不存在时,x 才是序列起点(避免重复计算)
if (hash.count(x - 1)) {
;
}
y = x + ;
(hash.(y)) {
++y;
}
len = (len, y - x);
}
len;
}
};

