LeeCode_128. 最长连续序列(哈希:map+set)

一、介绍

1.题目描述

题目链接:https://leetcode-cn.com/problems/longest-consecutive-sequence/submissions/

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

2.测试样例

[100,4,200,1,3,2] # 4

[0,3,7,2,5,8,4,6,0,1]  # 9

[9,1,4,7,3,-1,0,5,8,-1,6]  # 7

二、题解

1、哈希map🟢

思路:定义map记录出现过的数字,出现过则存入map标为1,在map中找最长连续序列

以[100,4,200,1,3,2]为例

  • 遍历一次数组后,map中存储[1:1,2:1,3:1,4:1,100:1,200:1]
  • 遍历map
    • 遇1,长度1,记录k=1,看接下来是否有2
    • 遇2,长度2,记录k=2,看接下来是否有3
    • ……
    • 遇100,更新当前答案=4,记录k=100,看接下来是否有101
    • ……
class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        int n=nums.size();
        map<int,int> mp; 
        for(int i=0;i<n;i++) mp[nums[i]]=1;  // 存储出现的数字
        map<int,int>::iterator it=mp.begin();
        int ans=0,temp_ans=0,k=it->first;
        while(it!=mp.end()){
            if(temp_ans==0) temp_ans++;   // 对于第一个数
            else if(k+1==it->first){   // 如果连续,个数+1
                temp_ans++;
                k++;
            }
            else{   // 如果不连续,更新答案,重置个数
                ans=max(ans,temp_ans);
                temp_ans=1;
                k=it->first;
            }
            it++;
        }
        ans=max(ans,temp_ans);  // 从某段开始到末尾都连续,结束后应更新答案
        return ans;
    }
};

image-20210921124737091

2、哈希set🟡

官方用的是一个更高效简便的方法。

思路:① 将数字存入到set中,set是一个元素不重复的集合。② 遍历 set,当遇到连续序列中最小的元素时(即set中没有更小的连续元素),递增统计连续序列的个数。

以[100,3,2,4,200,1,3,2]为例

  • 遍历一次数组后,set中存储[100,3,2,4,200,1]
  • 遍历set
    • 遇100,∵无元素99,∴是该连续序列的最小元素,向后查找连续序列,无101,总长度1 , 更新答案ans=max(ans,1)
    • 遇3,∵有元素2,∴非该连续序列中最小的元素,跳过;
    • ……遇2、4,与3同理
    • ……遇200,与100同理
    • 遇1,∵无元素0,∴是该连续序列的最小元素,向后查找连续序列,有234,总长度4,更新答案ans=max(ans,4)

参考链接:

https://leetcode-cn.com/problems/longest-consecutive-sequence/solution/zui-chang-lian-xu-xu-lie-by-leetcode-solution/
其实该方法用map也可以实现,不过原理相同,就不再写一次了

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        int n=nums.size();
        unordered_set<int> st;  // 集合记录所有不重复元素
        for(int i=0;i<n;i++) st.insert(nums[i]);
        int ans=0,ans_temp=0;
        for (const int& num : st){
            if(!st.count(num-1)){  // 当前连续序列中没有更小数,即当前数为该连续序列的最小数
                int k=num;
                ans_temp=1;
                while(st.count(k+1)){  // 统计连续序列长度
                    k++;
                    ans_temp++;
                }
                ans=max(ans,ans_temp);  // 更新答案
            }
        }
        return ans;
    }
};

image-20210921130427973

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值