128. 最长连续序列
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
int Longest = 0;
// So straightforward... Putting the whole vector into set is for both
// deduplication and O(1) search, which is very important.
unordered_set<int> Set(nums.begin(), nums.end());
for (int X : Set) {
// Do not search in the middle of consecutive sequences. This reduces a
// lot of time consumption.
if (Set.count(X - 1))
continue;
int ThisLength = 1;
// O(1) instead of O(n) search! We can just count from X + 1 instead of X
// since we have already counted X in the outer for-loop.
while (Set.count(X + 1)) {
++X;
++ThisLength;
}
Longest = max(ThisLength, Longest);
}
return Longest;
}
};
这个解决方案有点太简单粗暴了,但是确实有用,因为乱序数组的查找操作时间复杂度是 \(\mathrm O(n)\),而转换为 unordered_set 可以将查找操作变为 \(\mathrm O(1)\),再加上不从中间位置开始搜索的分支处理,整体的复杂度确实就是 \(\mathrm O(n\times1)=\mathrm O(n)\)。
二刷
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
int Result = 0;
unordered_set<int> Set(nums.begin(), nums.end());
for (int X : Set) {
// Just don't cut the rope at the middle. We need it whole.
if (Set.contains(X + 1))
continue;
// The outer loop is just for the X.
int Length = 1;
while (Set.contains(X - 1)) {
// Lengthen the rope.
++Length;
--X;
}
Result = max(Result, Length);
}
return Result;
}
};
我靠,这个我真的没想起来。而且说实话这个思路好像写起来也不是那么符合直觉。但是如果有analogy的话就好一点,比如
可以明显地看到我们为什么要忽略有\(X+1\)的情况,以及为什么int Length = 1;放在循环里面——因为外循环只是用来找起始点的,移动\(X\)计数是内循环干的事情,那么找到起始点之后自然就至少有了1的长度。
