题目
给定一个未排序的整数数组 nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n)
的算法解决此问题。
示例 1:
输入:nums = [100,4,200,1,3,2] 输出:4 解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
示例 2:
输入:nums = [0,3,7,2,5,8,4,6,0,1] 输出:9
思路
这道题技巧性很强,可以用哈希也可以用并查集,并查集把每个数字看成一个节点,链接关系就是数值比其大1,另外额外维护一个size,保存每个num能达到的最大值
并查集
python代码:
class Solution(object):
def longestConsecutive(self, nums):
nums = set(nums)
ans = 0
#离散的并查集,使用字典
fa = {num:num for num in nums} #存储每个节点的root,初始化为自己
size = {num:1 for num in nums} #存储以当前节点为root的节点数量
def find(x):
if fa[x] != x:
fa[x] = find(fa[x])
return fa[x]
def merge(f,to):
f = find(f)
to = find(to)
if f != to:
fa[f] = to
size[to] += size[f]
#遍历数组,如果满足合并关系就合并
for num in nums:
if num+1 in fa:
merge(num,num+1)
if size:
ans = max(size.values())
return ans
C++代码:
class Djset {
public:
unordered_map<int,int> parent;
unordered_map<int,int> size;
Djset(vector<int>& nums){
for(int i = 0;i < nums.size();i++){
parent.insert({nums[i],nums[i]}); //保存自己的父亲
size.insert({nums[i],1}); //记录自己的大小
}
}
int find(int x){
if(parent[x] != x){
parent[x] = find(parent[x]);
}
return parent[x];
}
void merge(int x,int y){
x = find(x);
y = find(y);
if(y != x){
parent[y] = x;
size[x] += size[y];
}
}
};
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
sort(nums.begin(),nums.end());
auto uniqueEnd = unique(nums.begin(),nums.end());
nums.resize(distance(nums.begin(),uniqueEnd));
Djset dj(nums);
for(int i = 0;i<nums.size();i++){
if(dj.parent.find(nums[i]+1) != dj.parent.end()){
dj.merge(nums[i]+1,nums[i]);
}
}
int ans = 0;
if(nums.size()){
for(int i = 0;i<nums.size();i++){
ans = max(ans,dj.size[nums[i]]);
}
}
return ans;
}
};
哈希
python代码:
class Solution(object):
def longestConsecutive(self, nums):
num_set = set(nums)
ans = 0
for num in nums:
if num - 1 not in num_set:
cur_num = num
cur_size = 1
while cur_num + 1 in num_set:
cur_num += 1
cur_size += 1
ans = max(ans,cur_size)
return ans
C++代码:
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_set<int> set;
for(int num:nums){
set.insert(num);
}
int ans = 0;
for(auto num:nums){
if(set.find(num-1) == set.end()){
//这里也可写成:if(!set.count(num-1))
int cur_num = num;
int cur_size = 1;
while(set.find(cur_num+1) != set.end()){
//这里也可写成:while(set.count(i+1))
cur_num += 1;
cur_size += 1;
}
ans = max(ans,cur_size);
}
}
return ans;
}
};