【LeetCode】128. 最长连续序列 结题报告 (C++)

原题地址:https://leetcode-cn.com/problems/longest-consecutive-sequence/description/

题目描述:

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

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

示例:

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

解题方案:

本题的类型是并查集,从来没有做过的题型。。学习学习!

初始思路是对数组进行排序,再查找最大的连续序列。因为题目要求时间复杂度为O(N),这种方式不可用。

将连续的数字合并为一个数组,最后比较这些数组,看哪个数组中的元素最多。。

并查集还是很妙的,其中的相关资料:http://www.cnblogs.com/horizonice/p/3658176.html

百度百科含有列题以及C++代码:https://baike.baidu.com/item/并查集/9388442?fr=aladdin#6_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])
            {
                _id[p] = _id[_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;    //记录是否有查复数字 或者 是否已经有数字的前后的数
        unordered_map<int, int> nums_disJointSetID_map; //<数字,ID> 与并查集ID一一对应,不需改动模板参数
        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/qq_32805671/article/details/82846691