原题地址: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;
}
};