法1:并查集+哈希,时间复杂度O(n)
class Solution {
public:
unordered_map<int, int> F;//<x,F[x]>
int father(int x) {
if (F[x] != x)
F[x] = father(F[x]);//并查集寻找并刷新根结点
return F[x];
}
int longestConsecutive(vector<int>& nums) {
F.clear();
for (auto x : nums)
F.insert(make_pair(x, x));//初始化
for (auto x : nums) {//初始时x=nums[0]
if (F.count(x - 1) > 0)
F[father(x - 1)] = father(x);//x-1所在集合从属于x所在集合
if (F.count(x + 1) > 0)
F[father(x)] = father(x + 1);//x所在集合从属于x+1所在集合
}
int res = 0;
for (auto x : nums)
if (father(x) - x + 1 > res)
res = father(x) - x + 1;
return res;
}
};
并查集算法还可以这样写:
int father(int x) {
int temp=x;
if (F[x] != x)
temp = father(F[x]);//并查集寻找根结点
return temp;
}
另一种写法:
class Solution {
public:
unordered_map<int, int> F;//<x,F[x]>
int father(int x) {
if (F.count(x) == 0)
return x;
if (F[x] != x)
F[x] = father(F[x]);
return F[x];
}
int longestConsecutive(vector<int>& nums) {
F.clear();
for (auto x : nums) {//初始时x=nums[0]
F[x] = father(x);//F[x]不存在时会自动创建
if (F.count(x - 1) > 0)
F[father(x - 1)] = father(x);
if (F.count(x + 1) > 0)
F[father(x)] = father(x + 1);
}
int res = 0;
for (auto x : nums)
if (father(x) - x + 1 > res)
res = father(x) - x + 1;
return res;
}
};
法2:排序,时间复杂度O(nlogn)
先将 nums 数组排序,并考虑除了第一个数字以外的每个数字与它前一个数字的关系。如果当前数字和前一个数字相等,那么我们当前的序列既不会增长也不会中断,我们只需要继续考虑下一个数字。如果不相等,我们必须要检查当前数字是否能延长答案序列(也就是 nums[i] == nums[i-1] + 1)。如果可以增长,那么我们当前序列长度加1,同时刷新最大序列长度,并继续。否则,当前序列被中断,我们记录当前序列的长度并将序列长度重置为 1 。
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
if (nums.size() == 0)return 0;
sort(nums.begin(), nums.end());
int current_length = 1;
int max_length = 1;
for (int i = 1; i < nums.size(); i++)
{
if (nums[i] != nums[i - 1])
{
if (nums[i] == nums[i - 1] + 1)
{
current_length++;
max_length = max(current_length, max_length);
}
else
{
max_length = max(current_length, max_length);
current_length = 1;
}
}
}
return max_length;
}
};