LeetCode 128.最长连续序列(Longest Consecutive Sequence)【并查集】【HashMap技巧】

7 篇文章 0 订阅
5 篇文章 0 订阅
给定一个未排序的整数数组,找出最长连续序列的长度。
要求算法的时间复杂度为 O(n)。

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

中等难度题吧,不算hard题,需要了解并查集用法
将连续的数字进行合并成一个集合,最后看所有集合中哪个集合数目最多(或者直接边合并边记录最大值)
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <set>
#include <map>
#include <unordered_set>
#include <iostream>
using namespace std;
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;
	}
};

int main()
{
	Solution Solution;
	vector<int> nums{ 100,4,200,1,3,2 };
	cout << Solution.longestConsecutive(nums) << endl;
}


网上另一种解法,使用HashMap进行存 nums[i] 值和其对应时刻下最长连续序列的长度。
通过搜寻当下nums[i]的左右临边值是否存在,从而在HashMap中进行修改 当前 子序列的两边界的value值(当前子序列的长度),方便后续的nuns[i]值进行搜索左右临边值,可以直接用(因为遇到相同的值,即HashMap中已经存在的,不需要再判断了,而且也不需要实时更新value值,只是需要更新当前子序列两端value值即可

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        if(nums.empty()) return 0;
        unordered_map<int, int> record;
        int max_count = 0;
        for(int i=0; i<nums.size(); i++)
        {
        	//已经判断过这个数,则不需要再判断第二遍
            if(record.find(nums[i]) != record.end()) continue;
            //当前数nums[i]的左右两边的数,对应的最长连续序列的个数(有可能没有左右两边的数,没有的话,个数就是0)
            int left = 0;
            int right = 0;
            if(record.find(nums[i]-1) != record.end())
                left = record[nums[i]-1];
            if(record.find(nums[i]+1) != record.end())
                right = record[nums[i]+1];
            int count = 1+left+right;
            //保存nums[i]在当前时刻的 最大连续序列的个数
            record[nums[i]] = count;
            //更修nums[i] 最远的 左右两边的数的 最大连续序列的个数
            if(left) record[nums[i]-left] = count;
            if(right) record[nums[i]+right] = count;
			
			//实时判断修改最大值
            if(max_count < count)
                max_count = count;
        }
        return max_count;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值