LeetCode Algorithms 128. Longest Consecutive Sequence 题解

Given an unsorted array of integers, find the length of the longest
consecutive elements sequence.

For example, Given [100, 4, 200, 1, 3, 2], The longest consecutive
elements sequence is [1, 2, 3, 4]. Return its length: 4.

Your algorithm should run in O(n) complexity.

题目是求一个无序数组的最长递增序列的长度,时间复杂度要求在O(n)以内,如果是有序数组的话,问题会简单很多,遍历数组找到最长的长度即可,虽然c++STL里面的sort函数时间复杂度最坏情况是O(nlogn),但是用在这个题目却可以AC,有点搞不懂。

既然可以sort,那么问题就很简单了,先排序,然后取出数组的头元素n,然后循环检查数组头元素是否等于n+1,是的话继续取出下一个并检查后续整数是否连续相等,否则停止,然后用当前的最长递增子序列的长度与之前记录的最大长度比较取最大值。代码如下(为了使用pop_back函数,我使用了降序排序):

int Solution::longestConsecutive(vector<int>& nums) {
    sort(nums.begin(), nums.end(), greater<int>());
    int res = 0;
    int num;
    while (!nums.empty()) {
        num = nums.back();
        nums.pop_back();
        int count = 1;
        while ((!nums.empty()) && num == nums.back() - 1) {
            num = nums.back();
            nums.pop_back();
            while (!nums.empty() && nums.back() == num) nums.pop_back();
            count++;
        }
        res = max(res, count);
    }
    return res;
}

以上是一种违背题目原意的做法,把复杂的部分都交给标准库去处理了,接下来讲一种O(n)复杂度的算法。

O(n)意味着遍历一遍或者几遍序列就要得到答案,那么储存结构就很重要了,不能使用有序的结构,因为插入查找等操作的复杂度超过要求,因此使用无序结构是优先考虑的。

这里可以使用unordered_set,它是基于hash函数储存数据的,因此访问其中的某个特定元素一般只需要O(1)的复杂度,最坏情况如所有数据都对应一个hash值,那么复杂度才会到达O(n),当然这是不现实的,基本上不会出现这种情况。

查找能达到O(1)复杂度,那么对于某个整数n,分别找它的前一个连续整数和后一个连续整数是否在序列中即可。记录下前后整数即可得到递增子序列的长度。代码如下:

int Solution::longestConsecutive(vector<int>& nums) {
    unordered_set<int> set(nums.begin(), nums.end());
    int res = 0;
    for (int n : nums) {
        if (set.find(n) == set.end()) continue;
        set.erase(n); // 使用erase删除已访问元素以减少重复查找
        int prev = n - 1, next = n + 1;
        while (set.find(prev) != set.end()) set.erase(prev--);
        while (set.find(next) != set.end()) set.erase(next++);
        res = max(res, next - prev - 1);
    }
    return res;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值