• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
fangleSea
博客园    首页    新随笔    联系   管理    订阅  订阅
代码随想录|动态规划
 理论基础 

509. 斐波那契数 

70. 爬楼梯 

746. 使用最小花费爬楼梯 

62.不同路径 

63. 不同路径 II 

343. 整数拆分 

96.不同的二叉搜索树


动态规划理论基础

动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。

所以动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的

对于动态规划问题,我将拆解为如下五步曲,这五步都搞清楚了,才能说把动态规划真的掌握了!

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

509. 斐波那契数

class Solution:
    def fib(self, n: int) -> int:
        if n == 0:
            return 0
        if n == 1:
            return 1
        return self.fib(n-1)+self.fib(n-2)

 


70. 爬楼梯

记住要由递归公式推导出dp公式

class Solution:
    def climbStairs(self, n: int) -> int:
        if n == 1:
            return 1
        if n == 2:
            return 2
        dp = [0 for _ in range(n+1)]
        dp[1] = 1
        dp[2] = 2
        for i in range(3, n+1):
            dp[i] = dp[i-1] + dp[i-2]
        return dp[n]

746. 使用最小花费爬楼梯

class Solution:
    def minCostClimbingStairs(self, cost: List[int]) -> int:
        n = len(cost)
        if n == 1:
            return 0
        if n == 2:
            return min(cost[0], cost[1])
        dp = [0 for _ in range(n)]
        dp[0] = cost[0]
        dp[1] = cost[1]
        for i in range(2, n):
            dp[i] = cost[i] + min(dp[i-1], dp[i-2])
        return min(dp[-1], dp[-2])
        

 


62.不同路径

class Solution:
    def uniquePaths(self, m: int, n: int) -> int: #M行 N列
        if m == 1 or n == 1:
            return 1
        dp = [[0 for _ in range(n)] for _ in range(m)]
        for i in range(n):
            dp[0][i] = 1
        for j in range(m):
            dp[j][0] = 1
        for j in range(1, m):
            for i in range(1,n):
                dp[j][i] = dp[j-1][i] + dp[j][i-1]
        return dp[-1][-1]

 


63. 不同路径 II

class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        n = len(obstacleGrid) #N行M列
        m = len(obstacleGrid[0])
        dp = [[0 for _ in range(m)]for _ in range(n)]
        if obstacleGrid[0][0] == 1:
            dp[0][0] = 0
        else:
            dp[0][0] = 1
        for i in range(1, m):
            if obstacleGrid[0][i] == 1:
                dp[0][i] = 0
            else:
                dp[0][i] = dp[0][i-1]
        for j in range(1, n):
            if obstacleGrid[j][0] == 1:
                dp[j][0] = 0
            else:
                dp[j][0] = dp[j-1][0]
        for j in range(1, n):
            for i in range(1, m):
                if obstacleGrid[j][i] == 1:
                    dp[j][i] = 0
                else:
                    dp[j][i] = dp[j-1][i] + dp[j][i-1]
        return dp[-1][-1]

 


343. 整数拆分

注意遍历所有切割点的时候只用遍历【0,i//2+1】

class Solution:
    def integerBreak(self, n):
        if n <= 3:
            return 1 * (n - 1)  # 对于n小于等于3的情况,返回1 * (n - 1)

        dp = [0] * (n + 1)  # 创建一个大小为n+1的数组来存储最大乘积结果
        dp[1] = 1  # 当n等于1时,最大乘积为1
        dp[2] = 2  # 当n等于2时,最大乘积为2
        dp[3] = 3  # 当n等于3时,最大乘积为3

        # 从4开始计算,直到n
        for i in range(4, n + 1):
            # 遍历所有可能的切割点
            for j in range(1, i // 2 + 1):
                # 计算切割点j和剩余部分(i - j)的乘积,并与之前的结果进行比较取较大值
                dp[i] = max(dp[i], dp[i - j] * dp[j])

        return dp[n]  # 返回整数拆分的最大乘积结果

96.不同的二叉搜索树

相乘的思想

class Solution:
    def numTrees(self, n: int) -> int:
        if n == 1:
            return 1
        dp = [0 for _ in range(n+1)]
        dp[0] = 1
        dp[1] = 1
        for i in range(2, n+1):
            for j in range(0,n):
                dp[i] += dp[j]*dp[i-j-1]
        return dp[n]   

 

posted on 2023-06-25 19:19  跪求个offer  阅读(39)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3