数组中的最长连续子序列

1,998 阅读2分钟

这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

##数组中的最长连续子序列

问题描述

给定无序数组arr,返回其中最长的连续序列的长度(要求值连续,位置可以不连续,例如 3,4,5,6为连续的自然数)。请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例:

输入:[100,4,200,1,3,2]

输出:4

说明:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

分析问题

因为给定的数组是无序的,所以我们最直观的想法就是遍历数组中的每个元素,然后考虑以其为起点,不断的在数组中寻找x+1,x+2,...,x+n是否存在,如果最长匹配到了x+n,那么就表明以x为起点的最长连续序列为x,x+1,x+2,...,x+n,其长度为n+1。因为在数组中寻找一个数是否存在,是需要O(n)的时间复杂度;而在哈希表中判断一个数是否存在只需要O(1)的时间复杂度,所以我们可以通过引入一个哈希表,来减低该算法的时间复杂度。

在最坏的情况下,该算法的时间复杂度是O(n^2)(即外层需要枚举n个数,内层也需要匹配n次),无法满足题目的要求,那我们如何来进行优化呢?

我们来分析一下算法的执行过程,如果我们已经知道了数组中存在有一个x,x+1,x+2,...,x+n的连续序列,那么我们就没有必要再继续以x+1,x+2,....,x+n为起点去数组中寻找连续序列了,因为得到的结果肯定不会优于以x为起点的连续序列。所以,我们在外层循环中如果碰到这种情况直接跳过就好。

具体做法是,我们在遍历的元素x时,去判读其前驱数x-1是否存在,如果存在的话,就不需要执行后面的逻辑,因为从x-1进行匹配的结果是优于从x进行匹配的,所以跳过x。

image-20211102171231831

image-20211102171302801

image-20211102171331739

下面我们来看一下代码的实现。

class Solution:
    def longestConsecutive(self, nums):
        #记录最长子序列的长度
        length = 0

        #将数组中的元素放入set中
        num_set = set(nums)

        for num in num_set:
            #判断num-1是否存在于哈希表中,如果存在,直接跳过
            if num - 1 not in num_set:
                currentdata = num
                currentlength = 1
                #继续寻找
                while currentdata + 1 in num_set:
                    currentdata += 1
                    currentlength += 1
                #取最大值
                length = max(currentlength, length)

        return length

该算法的时间复杂度是O(n),空间复杂度也是O(n)。