【算法】【动态规划篇】第10节:最长连续序列问题(leetcode 128. 最长连续序列)(使用hash表优化空间复杂度)

本期任务:介绍算法中关于动态规划思想的几个经典问题

【算法】【动态规划篇】第1节:0-1揹包问题

【算法】【动态规划篇】第2节:数字矩阵问题

【算法】【动态规划篇】第3节:数字三角形问题

【算法】【动态规划篇】第4节:硬币找零问题

【算法】【动态规划篇】第5节:剪绳子问题

【算法】【动态规划篇】第6节:最低票价问题

【算法】【动态规划篇】第7节:最长子串问题

【算法】【动态规划篇】第8节:最大正方形问题

【算法】【动态规划篇】第9节:乘积最大子数组问题

【算法】【动态规划篇】第10节:最长连续序列问题


问题来源

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

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

示例:

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

大佬解析

  • 【动态规划】Python 题解

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

代码


"""
需求:
    给定一个未排序的整数数组,找出最长连续序列的长度。
    要求算法的时间复杂度为 O(n)。
    
思想:
    多趟遍历法:(内存溢出)
        第一趟,找出数组中的最大和最小元素max_num、min_num,初始化数组,值为0,[min_num, max_num]
        第二趟,将出现过的位置置为1
        第三趟,找出最长连续子序列
        
    动态规划法:
        出于内存考虑,建一个dp_dict,用于存储以某个点为端点的最长连续子串长度
        维护一个最大长度值,遍历每个数字,最终得到最终结果

"""


class Solution:
    def longestConsecutive(self, nums) -> int:
        # 边界情况处理
        nums = set(nums)
        size = len(nums)
        if size in [0, 1]:
            return size

        hash_dict = dict()
        max_length = 0

        for num in nums:
            left = hash_dict.get(num - 1, 0)
            right = hash_dict.get(num + 1, 0)
            cur_length = left + right + 1
            max_length = max(max_length, cur_length)

            hash_dict[num] = cur_length
            hash_dict[num - left] = cur_length  # 只需关心num-left与num+right,其间的值不会再出现,细品
            hash_dict[num + right] = cur_length

        return max_length

    def longestConsecutive1(self, nums) -> int:
        """三趟遍历:内存溢出"""
        
        size = len(nums)
        if size in [0, 1]:
            return size

        # 第一趟,找出数组中的最大和最小元素max_num、min_num,初始化数组,值为0,[min_num, max_num]
        min_num, max_num = min(nums), max(nums)
        res = [0] * (max_num - min_num + 1)

        # 第二趟,将出现过的位置置为1
        for v in nums:
            res[v - min_num] = 1

        # 第三趟,找出最长连续子序列
        max_length = 0
        tmp = list()
        for i, v in enumerate(res):
            if v == 0:
                max_length = max(len(tmp), max_length)
                tmp = list()
            elif v == 1:
                tmp.append(i + min_num)
        max_length = max(len(tmp), max_length)
        return max_length

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章