《并查集》128. 最长连续序列《leetcode》

本文介绍了一种使用并查集数据结构解决最长连续数字序列问题的高效算法,时间复杂度达到O(n),适用于未排序整数数组。通过实例演示和代码实现,帮助读者理解如何利用并查集优化查找和合并操作以寻找最长连续序列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
    }
};

哈哈哈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值