20220301_datawhale34期_leetcode_10动规

十 动规

1.1 基础

动态规划(英语:Dynamic programming,简称 DP),是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题。

  • 即 >>> 搜索的优化

动态规划(DP, dynamic programming)是一种对问题的状态空间进行分阶段、有顺序、不重复、 决策性遍历的算法

  • 动态规划的关键与前提:
    重叠子问题——与递归、分治等一样,要具有同类子问题,用若干维状态表示
    最优子结构 ——状态对应着一个最优化目标,并且最优化目标之间具有推导关系
    无后效性——问题的状态空间是一张有向无环图(可按一定的顺序遍历求解)

  • 动态规划一般采用递推的方式实现
    也可以写成递归或搜索的形式,因为每个状态只遍历一次,也被称为记忆化搜索

  • 动态规划三要素:阶段、状态、决策

1.2 题目

1.2.1 53 . 最大子数组和

  • 思路: 𝑓[𝑖] 表示以 𝑖 为结尾的最大子序和
    𝑓 [𝑖] = max (𝑓 [𝑖 − 1] + 𝑛𝑢𝑚𝑠 [𝑖] , 𝑛𝑢𝑚𝑠[𝑖])
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        n = len(nums)
        f = [nums[0]]
        for i in range(1, n):
            f.append(max(nums[i], f[i - 1] + nums[i]))
        return max(f)

1.2.2 1143 . 最长公共子序列

  • 思路:只关心数量>>> 动规 >>> 观察蛮力搜索状态 >> 寻找变化信息 >>> 确定最优子结构, 边界

f[i][j]表示text1的前i个字符和text2的前j个字符能组成的LCS的长度
如果 text1[i] = text2[j]: f[i][j] = f[i - 1][j-1] + 1
如果 text1[i] != text2[j]: f[i][j] = max(f[i - 1][j], f[i][j-1] )

class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        m, n = len(text1), len(text2)
        f = [[0]*(n + 1) for _ in range(m + 1)]
        text1 = " " + text1   
        text2 = " " + text2
        for i in range(1, m + 1):
            for j in range(1, n + 1):
                if text1[i] == text2[j]:
                    f[i][j] = f[i - 1][j - 1] + 1
                else:
                    f[i][j] = max(f[i - 1][j], f[i][j - 1])
        return f[-1][-1]

1.2.3 121 . 买卖股票的最佳时机

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        dp1 = 0
        dp2 = 10e9
        for price in prices:
            dp2 = min(dp2, price)
            dp1 = max(dp1, price - dp2)
        return dp1

1.2.4 122 . 买卖股票的最佳时机 II

𝑓 [𝑖,𝑗]代表第 𝑖天结束时, 持有 𝑗股(0或1)
←表示max更新

  • 买: 𝑓 [𝑖, 1] ← 𝑓 [𝑖 − 1,0] − 𝑝𝑟𝑖𝑐𝑒𝑠 [𝑖]
  • 卖: 𝑓 [𝑖, 0] ← 𝑓 [𝑖 − 1,1] + 𝑝𝑟𝑖𝑐𝑒𝑠[𝑖]
  • 不买不卖: 𝑓 [𝑖,𝑗] ← 𝑓 [𝑖 − 1,𝑗]
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        prices = [0] + prices
        f = [[-1e9, -1e9] for _ in range(len(prices))]
        f[0][0] = 0
        for i in range(1, len(prices)):
            f[i][1] = max(f[i][1], f[i - 1][0] - prices[i])
            f[i][0] = max(f[i][0], f[i - 1][1] + prices[i])
            for j in range(2):
                f[i][j] = max(f[i][j], f[i-1][j])
        return f[-1][0]

1.2.5 516 . 最长回文子序列

  • 思路:
    dp[i][j]:字符串s在[i, j]范围内最长的回文子序列的长度为dp[i][j]。
    s[i] = s[j]时 >>
    dp[i][j] = dp[i + 1][j - 1] + 2;
    s[i] != s[j] 时 >>
    dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        n = len(s)
        dp = [[0]*n for _ in range(n)]
        for i in range(n-1, -1, -1):
            dp[i][i] = 1
            for j in range(i+1, n):
                if s[i] == s[j]:
                    dp[i][j] = dp[i + 1][j - 1] + 2
                else:
                    dp[i][j] = max(dp[i + 1][j], dp[i][j-1])
        return dp[0][-1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值