LeetCode 128最长连续序列

LeetCode 128最长连续序列Hard

  • 题目简述:给定一个未排序的整数数组,找出最长连续序列的长度。要求算法的时间复杂度为 O(n)。
  • 输入:[100, 4, 200, 1, 3, 2] 输出:4 解释:最长连续序列是 [1, 2, 3, 4]
  • 思路:双指针算法
    • 首先对未排序的数组进行排序,并将双指针都指向开始位置
    • 只要r指向的数字等于r-1指向的数字或者r-1指向的数字大1,那么r指针就向右移动扩大窗口,在移动过程中,当r指向的数字等于r-1指向的数字时,长度不变;当r指向的数字大r-1指向的数字1时,长度增加。
    • 如果发现r指向的数字不连续了,将r作为l的新起点重新开始窗口滑动
class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        if(nums.empty()) return 0;
        sort(nums.begin(), nums.end());
        int l = 0, r = 0, ans = 0;
        while(l <= r && l < nums.size() && r < nums.size())
        {
            r = l + 1;
            int count = 1;
            while(r < nums.size() && (nums[r] == nums[r - 1] || nums[r] == nums[r - 1] + 1))
            {
                if(nums[r] == nums[r - 1] + 1) count ++;
                r++;
            }
            ans = max(ans, count);
            l = r;
        } 
        return ans;
    }
};
  • 思路:哈希表去重

    将数组存入去重的哈希表中,只需要枚举每一个数尝试作为连续序列的起点,如果一个数是x,那么当它的前一个数x - 1不在哈希表中时,则该数就可能是一个新连续序列的起点,然后尝试查找x+1、x+2...x+n是否在哈希表中,只要遇到某个数不连续了就更新答案。

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        unordered_set<int> hash(nums.begin(), nums.end());
        int ans = 0;
        for(auto &x : nums)
        {
            if(!hash.count(x - 1))
            {
                int cur = 1;
                while(hash.count(x + cur)) cur++;
                ans = max(ans, cur);
            }
        }
        return ans;
    }
};
  • 思路三:
    • 哈希表记录每个点以及该点为边界的最大长度,这里只有区间端点的值才是真正的区间长度,而区间内部的的点的值仅起到记录该点出现过的意义。如果当前扫描到的数已经在哈希表中了,则直接跳过。
    • 当扫描到一个新数字时,找该数字左右数字的最大长度,合并后,更新该数字和新连续序列左右数字的哈希值。当遍历到 x 时,先求出 x−1的最大长度,则由于 x 第一次遍历到,所以x−1 如果存在,则一定是某个区间的右端点,同理 x+1 一定是某个区间的左端点。
class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        int ans = 0;
        unordered_map<int, int> hash;
        for(auto &x : nums)
        {
          if(hash[x]) continue;  //如果当前扫描到的数已经在哈希表中了,则直接跳过。
          hash[x] = 1;           //标记出现
          int left = hash[x - 1];//记录左右点包含的点个数
          int right = hash[x + 1];

          hash[x - left] = right + left + 1;//更新左右边界区间内点的个数
          hash[x + right] = right + left + 1;

          ans = max(ans, right + left + 1);
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值