【LeetCode】128. 最长连续序列

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012736685/article/details/88431345

一、题目描述

给定一个未排序的整数数组,找出最长连续序列的长度。

要求算法的时间复杂度为 O(n)。

二、示例

示例:

输入: [100, 4, 200, 1, 3, 2]
输出: 4

解释: 最长连续序列是 [1, 2, 3, 4]。它的长度为 4。

三、分析

  1. 思路一:使用sort排序,然后查找最大的连续序列。因为题目要求时间复杂度为 O(N) ,这种方式不可用。
  2. 使用并查集
    参考资料:

四、实现

并查集一般包含创建函数,查找函数,合并函数。

本代码设计很精妙,使用了并查集模块,在模块里直接定义了并查集的数组,以及查找函数和合并函数。

class Solution {
//	并查集模板(已优化)
    struct DisJointSet
    {
        vector<int> _id;      // 元素
        vector<int> _size;    // 集合内的元素个数
        int max_size;         // 最大集合的元素个数【额外需要用到的参数】
        int _count;           // 集合总个数
        DisJointSet(int Num)
        {
            for (int i = 0; i < Num; i++)
            {
                _id.emplace_back(i);
                _size.emplace_back(1);
            }
            _count = Num;
            max_size = 1;
        }
        //  查找
        int find_(int p)
        {
            while (p != _id[p])   
            {
                p = _id[p];
            }
            return p;
        }
        //  合并
        void _union(int p, int q) {
            int i = find_(p);
            int j = find_(q);
            if (i == j)
            	return;
            if (_size[i] > _size[j])
            {
                _id[j] = i;
                _size[i] += _size[j];
                max_size = max(max_size, _size[i]);
            }
            else
            {
                _id[i] = j;
                _size[j] += _size[i];
                max_size = max(max_size, _size[j]);
            }
            _count--;
        }
    };
public:
    int longestConsecutive(vector<int>& nums) {
        if (nums.size() == 0)
            
            return 0;
        DisJointSet disJointSet(nums.size());
        // 记录是否有查复数字 或者 是否已经有数字的前后的数
        unordered_set<int> nums_set;    
        // <数字,ID> 与并查集ID一一对应,不需改动模板参数
        unordered_map<int, int> nums_disJointSetID_map; 
        for (int i = 0; i < nums.size(); i++)
        {
            if (nums_set.find(nums[i]) != nums_set.end())
            	// 存在重复数字
            	continue;   
            nums_set.insert(nums[i]);
            nums_disJointSetID_map[nums[i]] = i;
            // 是否有前一个数
            if(nums_set.find(nums[i] - 1) != nums_set.end())    
            {
                disJointSet._union(nums_disJointSetID_map[nums[i]], nums_disJointSetID_map[nums[i] - 1]);
            }
            // 是否有后一个数
            if(nums_set.find(nums[i] + 1) != nums_set.end())    
            {
                disJointSet._union(nums_disJointSetID_map[nums[i]], nums_disJointSetID_map[nums[i] + 1]);
            }
        }
        return disJointSet.max_size;
    }
};

猜你喜欢

转载自blog.csdn.net/u012736685/article/details/88431345