128. 最长连续序列

Posted 炫云云

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了128. 最长连续序列相关的知识,希望对你有一定的参考价值。

128. 最长连续序列

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

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

示例 1:

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

哈希表

我们考虑枚举数组中的每个数 x x x​​, 考虑以其为起点, 不断尝试匹配 x + 1 , x + 2 , ⋯ x+1, x+2, \\cdots x+1,x+2,​​ 是否存在,假设 最长匹配到了 x + y x+y x+y​​, 那么以 x x x​​ 为起点的最长连续序列即为 x , x + 1 , x + 2 , ⋯   , x + y x, x+1, x+2, \\cdots, x+y x,x+1,x+2,,x+y​​, 其长度为 y + 1 y+1 y+1​​, 我们不断枚举并更新答案即可。

对于匹配的过程用一 个哈希表存储数组中的数, 这样查看一个数是否存在即能优化至 O ( 1 ) O(1) O(1)​​ 的时间复杂度。

仅仅是这样我们的算法时间复杂度最坏情况下还是会达到 O ( n 2 ) O\\left(n^{2}\\right) O(n2)​​ (即外层需要枚举 O ( n ) O(n) O(n)​​ 个数, 内层 需要暴力匹配 O ( n ) O(n) O(n)​​ 次),无法满足题目的要求。但仔细分析这个过程,我们会发现其中执行了很 多不必要的枚举, 如果已知有一个 x , x + 1 , x + 2 , ⋯   , x + y x, x+1, x+2, \\cdots, x+y x,x+1,x+2,,x+y​​ 的连续序列,而我们却重新从 x + 1 x+1 x+1​​, x + 2 x+2 x+2​​ 或者是 x + y x+y x+y​​ 处开始尝试匹配,那么得到的结果肯定不会优于枚举 x x x​​ 为起点的答案,因此我们 在外层循环的时候碰到这种情况跳过即可。

那么怎么判断是否跳过呢?由于我们要枚举的数 x x x​​ 一定是在数组中不存在前驱数 x − 1 x-1 x1​​ 的,不然按 照上面的分析我们会从 x − 1 x-1 x1​​ 开始尝试匹配,因此我们每次在哈希表中检查是否存在 x − 1 x-1 x1​​​ 即能判断是否需要跳过了。

class Solution:
    def longestConsecutive(self, nums):
        longest_streak = 0
        num_set = set(nums) 

        for num in num_set: 
            if num - 1 not in num_set: # 不存在前驱数 x-1
                current_num = num      # 当前匹配数字
                current_streak = 1     # 当前匹配长度

                while current_num +1 in num_set: # 查看x+1是否在哈希表中
                    current_num +=1           # 当前匹配数字 x+1
                    current_streak +=1         # 当前匹配长度 +1
                
                longest_streak = max(longest_streak, current_streak)

        return longest_streak

  • 用哈希表存储每个端点值对应连续区间的长度
  • 若数已在哈希表中:跳过不做处理
  • 若是新数加入:
    • 取出其左右相邻数已有的连续区间长度 left 和 right
    • 计算当前数的区间长度为:cur_length = left + right + 1
    • 根据 cur_length 更新最大长度 max_length 的值
    • 更新区间两端点的长度值

class Solution(object):
    def longestConsecutive(self, nums):
        hash_dict = dict()
        max_length = 0
        for num in nums:
            if num not in hash_dict:
                # 判断左右是否可以连起来
                left = hash_dict.get(num - 1, 0)
                right = hash_dict.get(num + 1, 0)
                # 记录长度
                cur_length = 1 + left + right
                if cur_length > max_length:
                    max_length = cur_length
                
                hash_dict[num] = cur_length
                # 把头尾都设置为最长长度
                hash_dict[num - left] = cur_length
                hash_dict[num + right] = cur_length
            
        return max_length

参考

Krahets - 力扣(LeetCode) (leetcode-cn.com)

以上是关于128. 最长连续序列的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 128. 最长连续序列

LeetCode 128. 最长连续序列

128.最长连续序列

128.最长连续序列

LeetCode 128. 最长连续序列c++/java详细题解

128. 最长连续序列