最长递增子序列 -- 动规

300. 最长递增子序列

注意「⼦序列」和「⼦串」的区别,⼦串⼀定是连续的,⽽⼦序列不⼀定是连续的。

python 复制代码
class LengthOfLIS:
    """
    300. 最长递增子序列
    https://leetcode.cn/problems/longest-increasing-subsequence/description/
    """

    def solution(self, nums: List[int]):
        """
        方案一: 动态规划
        辅助数组 dp,dp[i] 表示以nums[i]结尾的子序列的最大长度
        时间复杂度O(N^2)
        空间复杂度O(N)
        :param nums:
        :return:
        """
        n = len(nums)
        dp = [1] * n
        for i in range(1, n):
            tmp = 0
            for j in range(0, i):
                if nums[j] < nums[i]:
                    tmp = max(tmp, dp[j])
            dp[i] = tmp + 1
        return max(dp)

    def solution2(self, nums: List[int]):
        """
        方案二:动态规划
        辅助数组 ends,ends[i] 代表目前所有长度为i+1的递增子序列的最小结尾。
        可推断出 ends 也是递增序列
        时间复杂度O(N*logN)
        空间复杂度O(N)
        :param nums:
        :return:
        """
        if not nums:
            return 0

        n = len(nums)
        ends = [0] * n
        ends[0] = nums[0]
        l, r, m, right = 0, 0, 0, 0
        res = 1
        for i in range(1, n):
            l = 0
            r = right
            while l <= r:
                m = (l + r) // 2
                if nums[i] > ends[m]:
                    l = m + 1
                else:
                    r = m - 1
            print(right, l)
            right = max(right, l)
            ends[l] = nums[i]
            res = max(res, l + 1)

        return res

    def solution3(self, nums: List[int]) -> int:
        """
        模拟蜘蛛纸牌
        :param nums:
        :return:
        """
        top = [0] * len(nums)
        #  牌堆数初始化为 0
        piles = 0
        for i in range(len(nums)):
            poker = nums[i]

            left, right = 0, piles
            while left < right:
                mid = left + (right - left) // 2
                if top[mid] > poker:
                    right = mid
                elif top[mid] < poker:
                    left = mid + 1
                else:
                    right = mid

            # 没找到合适的牌堆,新建⼀堆
            if left == piles:
                piles += 1
            # 把这张牌放到牌堆顶
            top[left] = poker

        return piles
相关推荐
俊俊几年的7 小时前
动态规划(Dynamic Programming)详解:从入门到 LeetCode Hot 100
linux·c++·算法·leetcode·嵌入式·动态规划·c
小此方4 天前
[算法实战论:动态规划]背包问题概念,01不满背包问题,01满背包问题,背包问题的滚动数组空间优化
算法·动态规划
冻柠檬飞冰走茶6 天前
字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)
c语言·开发语言·数据结构·算法·动态规划
Dream it possible!7 天前
LeetCode 面试经典 150_多维动态规划_交错字符串(97_C++_中等)
算法·leetcode·面试·动态规划
小此方7 天前
[算法实战论:动态规划]回文串问题的dp解法,回文串问题的母题,以及以此为基础的派生题
算法·动态规划
-梅7 天前
算法(1) 动态规划
算法·动态规划
UIU1148 天前
P1481 魔族密码
c++·算法·动态规划
j7~12 天前
【动态规划算法专题】动态规划五部曲实战:泰波那契数、三步问题、最小花费爬楼梯
c++·算法·动态规划·数据结构与算法
Tisfy12 天前
LeetCode 3665.统计镜子反射路径数目:三个动态规划数组
leetcode·动态规划·代理模式·题解
Tisfy13 天前
LeetCode 3882.网格图中最小异或路径:动态规划
算法·leetcode·动态规划