LeetCode/最长连续序列

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

1. 暴力法

排序后遍历
class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        //暴力
        sort(nums.begin(),nums.end());
        int n =nums.size();
        if(n==0) return 0;
        int count = 1;
        int res = 1;
        for(int i = 1; i < n; i++){
            if(nums[i]==nums[i-1]) continue;
            else if(nums[i]==nums[i-1]+1) count++;
            else  count = 1;
            res = max(res,count);
        }
        return res;
    }
};

2. 集合(哈希表)

先存储,再查找,跟两数之和那道题思路一样

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
            int n = nums.size();
            if(n==0) return 0;
            unordered_set<int> set_(nums.begin(),nums.end());
            int res = 1;
            for(int i=0;i<n;i++){
                if(!set_.count(nums[i])) continue;
                int count = 0;
                int num = nums[i];
                while(set_.count(num-1))
                    num--;//找到起始值   
                while(set_.count(num)){//遍历该序列
                    set_.erase(num);
                    num++;
                    count++;
                }
            res = max(res,count);
            }
            return res;
      }
};

3. 并查集

遍历所有元素num,如果num+1存在,将num加入到num+1所在的连通分量中(从后往前效果更好)
最后每个集合的根节点为其右边界,为了union操作,必须知道指定数值的元素在哪个位置
因为每次合并不是邻近元素合并,所以不能光用一个数组记录根节点,还需要我们使用map容器记录值到索引的映射,从而帮助合并找到对应索引
索性直接用map记录值跟索引,因为我们只关心序列的长度,这里索引直接就是该集合的右边界,也就是根节点值

class Solution {
public:
    unordered_map<int,int> series;//指针关系
    unordered_map<int,int> count;//用于合并时计数
    int max_ = 1;
    int longestConsecutive(vector<int>& nums) {
       if(nums.size()==0) return 0;
       for(int num:nums){
            series[num]=num;//每个数建立一个集合
            count[num]=1;//初始值为1
            }
        for(int i = nums.size()-1; i>=0; i--)
            if(series.count(nums[i]+1))   union_(nums[i]);

        return max_;
    }
    void union_(int num){
        int right1 = find(num);
        int right2 = find(num+1);
        if(right1==right2) return;
        series[num]=right2;//合并集合
        count[right2]=count[right1]+count[right2];//合并计数
        max_ = max(max_,count[right2]);//记录最大值
    }
    int find(int num){
        if(series[num]==num) return num;
        series[num] = find(series[num]);//压缩路径
        return series[num];
    }
};
posted @ 2022-06-05 23:38  失控D大白兔  阅读(27)  评论(0编辑  收藏  举报