128. 最长连续序列
难度困难609
给定一个未排序的整数数组 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
提示:
0 <= nums.length <= 104
-109 <= nums[i] <= 109
思路解析:
并查集:建立两个hashMap,一个是root 保留当前节点的父节点,一个是size保留以当前节点为根节点的子树层数。
首先初始化,遍历节点,节点的父节点是自己,子树层数是1
其次,遍历节点,如果当前节点的数值+1,存在的话,合并两个子树。更新size
最后,遍历节点,找到最大size,
要注意的是,防止nums的大小为0。
如图所示,建立个单链树。[100,4,200,1,3,2]
返回4的size即可。
AC代码:
class Solution {
public Map<Integer,Integer>root=new HashMap<Integer,Integer>();
public Map<Integer,Integer>size=new HashMap<Integer,Integer>();
public Integer find(int x)//找寻父节点
{
if(!root.containsKey(x))
return null;
while(x!=root.get(x))
x=root.get(x);
return x;
}
public void union(int x,int y)// y=x+1
{
int rootX=find(x);
int rootY=find(y);
if(rootX!=rootY)
{
root.put(rootX,rootY);
size.put(rootY,size.get(rootY)+size.get(rootX));
}
return;
}
public int longestConsecutive(int[] nums) {
for(int i=0;i<nums.length;i++)
{
root.put(nums[i],nums[i]);
size.put(nums[i],1);
}
for(int i=0;i<nums.length;i++)
if(find(nums[i]+1)!=null)
union(nums[i],nums[i]+1);
int maxLen=1;// 如果没有序列,最差是1
for(int i : nums)
maxLen=Math.max(maxLen,size.get(find(i)));
return nums.length==0? 0:maxLen;
}
}
注意一点:
首先Integer可以有null的出现,但int 不行。
其次,for(int i: num) 真的好用。
并查集也大概了解一下吧。
最后:放个马老师的段子
我啪的一下一个sort(),很快嗷,然后一个遍历,直接通过,按传统编程,点到即止,我已经赢了。这时候他一个时间复杂度为 O(n)打过来,我大意了,没有闪,我说小力扣你不讲武德,来偷袭我这22岁的老同志,这好吗,这不好。我劝,这位小力扣耗子为汁,好好反思,不要再犯这样的错误。
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
int len=nums.size(),maxlen=1,ans=1;
if(len<1)
return 0;
sort(nums.begin(),nums.end());
for(int i=1;i<len;i++){
if(nums[i]==nums[i-1])
continue;
if(nums[i]==nums[i-1]+1)
{
maxlen++;
ans=max(ans,maxlen);
}
else
maxlen=1;
}
return ans;
}
};
哈哈哈。