【刷题日记】leetcode128 最长连续序列

给定一个未排序的整数数组,找出最长连续序列的长度。

要求算法的时间复杂度为 O(n)

示例:

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

思路:

难点在于算法复杂度要求。

复杂度嘛。一点一点降下来

1. 最好想的暴力枚举

将数组的每个元素作为序列起始( O ( n ) O(n) O(n)),
逐个枚举下一个元素 O ( n ) O(n) O(n)
检查下一个元素在不在数组中 O ( n ) O(n) O(n)

2. 数组排序后一次遍历( O ( n l o g n ) O(nlogn) O(nlogn)

(1)数组排序
(2)类似滑动窗(但窗口大小只是窗口内不同元素的个数):
左端起始点初始化为数组的第0个元素
从第1号元素开始遍历:
如果遍历元素等于前一个元素:
- 那么他不能让序列边长,也不能在这里截断!!!
- 所以continue就完事了
如果遍历元素不等于前一个元素:
- 那看看他是不是前一个元素+1:
+ 是的话:当前序列长度+1
+ 不是的话:更新最长序列长度,更新当前序列长度为1(或者更新左端起点为当前遍历元素,即连续序列重新开始)
总之一次排序+一次遍历

3. HASH检查,空间换时间

暴力方法会超时的主要原因在于,枚举是查找数组的需要顺序查找太费时间了。
但是如果不是查找数组而是查找hash表,复杂度就成了 O ( 1 ) O(1) O(1)
枚举的起始点元素也在HASH表中找,没有起始点遍历,复杂度也是 O ( 1 ) O(1) O(1)
那么复杂度就只有确定每个序列起始点后,枚举的 O ( n ) O(n) O(n)

  • python中HASH的实现
    • 需要计数之类的可以用dict
    • 不需要计数其实可以用set !!! 神器啊。查找set的复杂度是O(1)惊不惊喜意不意外,这才是他跟list本质的不同。

三个思路代码如下:


class Solution:
    # O(n^3) 超时暴力枚举
    def longestConsecutive(self,nums):
        if len(nums) ==0:
            return 0
        longest = 0
        for item in nums:
            count = 1
            start = item+1
            while start in nums:
                start+=1
                count+=1
            if longest<count:
                longest = count
        return longest
    # O(nlogn)
    def longestConsecutive2(self, nums):
        if len(nums) == 0:
            return 0
        # O(nlogn)
        nums.sort()
        # 滑动窗检查O(n)
        longest = 1
        length = 1
        #left = 0
        #res =[] #用来保存最长结果,如果需要返回的话
        for scanner in range(1,len(nums)):
            #current_res = [nums[left]]
            # 当前扫描数字不等于前一个数,检查他是否可以加入连续序列
            if nums[scanner]!=nums[scanner-1]:
                if nums[scanner] == nums[scanner-1]+1:
                    length+=1
                    #current_res.append(nums[scanner])
                else:
                    longest = max(length,longest)
                    length = 1
                    # if longets == length:
                    #    res = current_res
                    #left = scanner
            # 相等的话不影响序列长度
            else:
                continue

        return max(longest,length)
    # O(n):
    # 暴力方法改为借助哈希表表,空间换时间:
    # 不去不断搜索当前数字+1在不在数组中。
    # 遍历数组过程中,存hash表。之后去搜索当前数-1在不在hash表。复杂度O(1)
    def longestConsecutive3(self, nums):
        longest = 0
        # 存成HASH
        num_set = set(nums)

        for start in num_set:
            if start-1 not in num_set:
                # start为起始左端
                current = start+1 
                while current in num_set:
                    current+=1 # current+1
                longest = max(longest,current-start)
        return longest
    # dict版: 多费点内存
    def longestConsecutive4(self, nums):
        num_dict = {}
        for item in nums:
            if item not in num_dict.keys():
                num_dict[item] = 1
            else:
                continue
        longest = 0
        for start in list(num_dict.keys()):
            if start-1 not in num_dict.keys():
                current = start+1
                while current in num_dict.keys():
                    current += 1
                longest = max(current-start, longest)
        return longest
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值