128 longest-consecutive-sequence
题目:
给定一个未排序的整数数组,找出最长连续序列的长度。
要求算法的时间复杂度为 O(n)。
输入: [100, 4, 200, 1, 3, 2]
输出: 4
解释: 最长连续序列是 [1, 2, 3, 4]。它的长度为 4。
思路
最直接的想法是排序,然后数连续的长度,但是要求是O(n),所以想到用set存储,然后数数。因为每个数只会被数一遍,所以时间复杂度为O(2n)。
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
int ans = 0;
unordered_set<int> s(nums.begin(), nums.end());
for(auto n: nums)
{
if(!s.count(n+1)) //是连续子数组中的最大值
{
int cnt = 0;
while(s.count(n)) //数数
{
cnt++;
n--;
}
ans = max(ans, cnt);
}
}
return ans;
}
};
另一种是用unordered_map来存储出每个数出现的子数组的开始和结束位置,利用了hash表,原理上是相同的。
class Solution {
public:
// merge过后,只剩下连续序列两端的值对应的长度是有意义的,中间的部分不会再访问(所以不更新)
int merge(unordered_map<int, int>& m, int small, int large)
{
int left = small - m[small] + 1;
int right = large + m[large] - 1;
int len = right - left + 1;
m[left] = len;
m[right] = len;
return len;
}
int longestConsecutive(vector<int>& nums) {
if(nums.size() <= 1)
return nums.size();
int ans = 1;
unordered_map<int, int> m;
for(auto n: nums)
{
if(m.find(n)!=m.end())
continue;
m[n] = 1;
if(m.find(n-1) != m.end())
{
ans = max(ans, merge(m, n-1, n));
}
if(m.find(n+1) != m.end())
{
ans = max(ans, merge(m, n, n+1));
}
}
return ans;
}
};