Leetcode 128最长连续序列

题目要求时间复杂度为O(n),由此可见,排序肯定不行的。在O(n)时间下第一个想到的就是哈希,这里可用Map解决。怎么样找到连续的序列呢,可以用到并查集。连续的序列为一个集合,在用个结构存放每个集合中元素个数就行了。

并查集具体的操作过程:每遍历到一个数,就看集合中是否存在它前一个数,若存在,则他的父节点就为前一个数,按照这个思路排下去,每个集合中都是连续的。

本来这些都可用数组搞定,但是题目的数据范围为1e9,数组开不了那么大,只能用map了。

下面给出Leetcode和本地编译器的代码。

Leetcode

/*
 * @lc app=leetcode.cn id=128 lang=cpp
 *
 * [128] 最长连续序列
 */

// @lc code=start
#define INF 0x3f3f3f3f
struct deNum{
 int value = INF;//初始化为INF,因为默认的为0,但是又有0这个元素
};
struct deV{
 int cnt = 1;
};
map<int,deNum> mp;//父节点Map key-》value(本节点,父节点)
map<int,deV> Max;//个数Map key-》value(本节点,本节点所在集合个数)
int findfa(int x)
{
   if(x != mp[x].value){
    mp[x].value = findfa(mp[x].value);
   }
   return mp[x].value;
}
void Union(int x,int y)
{
    int fax = findfa(x);
    int fay = findfa(y);
    if(fax != fay){
      mp[fax].value = fay;
      Max[fay].cnt += Max[fax].cnt;
    }

    //printf("x : %d, fa: %d\n",x,mp[x].value);
}
class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        for(int i = 0; i < nums.size(); i++){
            mp[nums[i]].value = nums[i];
            Max[nums[i]].cnt = 1;
        }
        for(int i = 0; i < nums.size(); i++){
        if(mp[nums[i] - 1].value != INF && mp[nums[i]].value != INF){//验证集合中是否存在前一个数,存在,则合并
        Union(nums[i],nums[i] - 1);
      }
    }
        int MAX = 0;
        map<int,deV>::iterator iter;
        for(iter = Max.begin(); iter != Max.end(); iter++){
            MAX = max(MAX,iter->second.cnt);
        }
        mp.clear();
        Max.clear();  
        return MAX;

    }
};
// @lc code=end

编译器代码 可用来debug

#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <stdio.h>
#include <ctype.h>
#include <bitset>
#include <sstream>
#define  LL long long
#define  ULL unsigned long long
#define mod 99997867
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define MODD(a,b) (((a%b)+b)%b)
using namespace std;
const int maxn = 1e3 + 5;
const int NUM = 1e6 + 5;
int n,m;
int dis[NUM];
struct deNum{
 int value = INF;
};
struct deV{
 int cnt = 1;
};
map<int,deNum> mp;
map<int,deV> Max;
int findfa(int x)
{
   if(x != mp[x].value){
    mp[x].value = findfa(mp[x].value);
   }
   return mp[x].value;
}
void Union(int x,int y)
{
    int fax = findfa(x);
    int fay = findfa(y);
    if(fax != fay){
      mp[fax].value = fay;
      Max[fay].cnt += Max[fax].cnt;
    }
}
int main()
{
    int a[maxn];
    scanf("%d",&n);
    for(int i = 0; i < n; i++) scanf("%d",&a[i]);
    for(int i = 0; i < n; i++) mp[a[i]].value = a[i],Max[nums[i]].cnt = 1;
    for(int i = 0; i < n; i++){
      if(mp[a[i] - 1].value != INF && mp[a[i]].value != INF){
        Union(a[i],a[i] - 1);
      }
    }
    for(int i = 0; i < n; i++) findfa(a[i]);
    int MAX = 0;
    map<int,deV>::iterator iter;
    for(iter = Max.begin(); iter != Max.end(); iter++){
      MAX = max(iter->second.cnt,MAX);
    }
    printf("%d\n",MAX);
    return 0;
}
/*
6
100 2 200 1 3 4
10
0 3 7 2 5 8 4 6 0 1
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值