每日一题--最长连续序列

本文介绍了LeetCode题目128:最长连续序列的三种解法,包括暴力枚举、哈希表遍历以及并查集,分析了各自的时间复杂度,并对不同方法进行了总结。
摘要由CSDN通过智能技术生成

洛阳春-岑参

人到洛阳花似锦,偏我来时不逢春。

谁道三冬无春色,冰山高处万里银

目录

题目描述

思路分析

方法及其时间复杂度

法一 暴力枚举:

法二 哈希表遍历:

法三 并查集:

个人总结


题目描述

128. 最长连续序列 - 力扣(LeetCode) 

思路分析

先预处理排序,再枚举所有连续区间并计算长度,选择最大的连续区间最长的那个。

方法及其时间复杂度

法一 暴力枚举:

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        sort(nums.begin(),nums.end());//先排序数组
        int n=nums.size();
        if(n==1) return 1; //为了防止下标越界,特殊处理
        int ans=0,Maxn=1; //记录最后答案,和记录连续区间的长度
        for(int i=1;i<n;++i){
            while(i<n&&(nums[i]==nums[i-1]+1||nums[i]==nums[i-1])){ //进入连续区间
                if(nums[i]==nums[i-1]) i++; //数字相同时,下标加1
                else   Maxn++,i++; //不相同说明连续,则计数器加1,下标加1
            }
            ans=max(Maxn,ans);  //每一个连续区间结束,选择最大的连续区间数作为答案
            Maxn=1;  //重置计数为1
        }
        return ans;
    }
};

时间复杂度O(nlogn) 排序的时间nlogn,遍历时间复杂度O(n)

法二 哈希表遍历:

  将数组全部插入哈希表,然后遍历哈希表,如果当前数-1在哈希表中不存在,就设当前数为连续区间的起点,一直在哈希表中查找当前的下一个,找到计数器加1,直到找不到为止,在更新最大值作为答案。

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        unordered_set<int> hash(nums.begin(),nums.end());  //将所有数插入哈希表
        int ans=0;
        for(const auto& x:hash){  //遍历哈希表
            if(!hash.count(x-1)){  //如果该数-1没有在哈希表,可以作为起点
                int y=x+1;  
                while(hash.count(y)) y++; //一直查找下一个数,直到找不到为止
                ans=max(ans,y-x);  //取每个区间的最大长度
            }
            
        }
        return ans;
    }
};

时间复杂度O(n),空间复杂度O(n)

法三 并查集:

假定原数组中的每个元素都以自己本身为根的集合,且每个集合大小都是1。

遍历数组元素,如果集合中存在当前元素-1或+1则合并到一个集合中。最后返回集合最大那个大小

 

class Solution {
public:
    unordered_map<int,int> pre; 
    unordered_map<int,int> sz;
    int root(int x){
        while(pre[x]!=x) x=pre[x];  //循环找根节点
        return x;
    }
    void merge(int x,int y){  //启发式合并,合并两个集合
        x=root(x),y=root(y);
        if(x==y) return ;
        if(sz[x]>sz[y])swap(x,y);
        pre[x]=y;
        sz[y]+=sz[x];
    }
    int longestConsecutive(vector<int>& nums) {
        for(const auto& x:nums){
            if(!pre.count(x)) pre[x]=x,sz[x]=1;  //初始化并查集
            if(pre.count(x-1)) merge(x,x-1);    //如果存在x-1或x+1则合并
            if(pre.count(x+1)) merge(x,x+1);
        }
        int ans=0;
        for(const auto& t:sz){  //查找合并集合里最大的
            ans=max(ans,t.second);
        }
        return ans;
    }
};

 时间复杂度O(nlogn) 空间复杂度O(n)

个人总结

多日没刷题,又怀念刷题的感觉,今日重启每日一诗系列

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值