leetcode刷题-动态规划part02

62.不同路径

leetcode题目链接
代码随想录文档讲解

思路

若使用图论中的深度搜索、广度搜索,提交超时

  1. dp数组的含义:从[0,0]到[i,j]有多少种不同的路径
  2. dp[i][[j] = dp[i-1][j] + dp[i][j-1]
  3. 初始化,每一个状态都是从上面和左面得出来的,所以要初始化最上面一行和最左边一行:dp[0][j] = 1; dp[i][0] = 1
  4. 遍历顺序:从左向右,从上往下

在这里插入图片描述

伪代码(C++)

 

python代码

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        dp = [[1]*n]*m
        for i in range(1, m):
            for j in range(1, n):
                dp[i][j] = dp[i-1][j]+dp[i][j-1]
        return dp[m-1][n-1]

63.不同路径 II

leetcode题目链接
代码随想录文档讲解

思路

在不同路径题目中添加了障碍

  1. dp数组的含义:从[0,0]到达[i,j]有多少不同的路径
  2. 递推公式:dp[i][j] = dp[i-1][j] + dp[i][j-1] if obs[i][j] ==0
  3. 初始化:因为有了障碍,(i, j)如果就是障碍的话应该就保持初始状态(初始状态为0),并且之后的也全为0,初始化代码如下(for循环的终止条件添加一个obs判断)【如果起始位置和结束位置有障碍,那就是0种路径】
vector<vector<int>> dp(m, vector<int>(n, 0));
for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1;
for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1;

==注意:==数组初始化要这么写:dp = [[0] * n for _ in range(m)]
在这里插入图片描述

伪代码(C++)

 

python代码

class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
    	# 可添加判断起始位置和终止位置是否为0的代码,降低复杂度
        m, n = len(obstacleGrid), len(obstacleGrid[0])
        # dp数组初始化
        dp = [[0] * n for _ in range(m)]
        # dp = [[0]*n]*m
        for i in range(m):
            if obstacleGrid[i][0] != 0:
                break
            dp[i][0] = 1
        for j in range(n):
            if obstacleGrid[0][j] != 0:
                break
            dp[0][j] = 1
            
        for i in range(1, m):
            for j in range(1, n):
                if obstacleGrid[i][j] == 0:
                    dp[i][j] = dp[i-1][j] + dp[i][j-1]
        return dp[m-1][n-1]

343. 整数拆分 再看

本题思路并不容易想,一刷建议可以跳过。如果学有余力,可以看视频理解一波。

leetcode题目链接
代码随想录文档讲解

思路

example:拆10
10 = 2 × 8 (10的状态依赖2和8的状态)
8 = 2 + 6 (8的状态依赖2和6的状态)
可使用动态规划来解决此问题:

  1. dp 的含义:dp[i] i拆分后最大的乘积为dp[i]
  2. 递推公式:dp[i] = max(dp[i], (i - j) * j, dp[i - j] * j)
    i = j + (i-j), 再对i-j继续进行拆分
  3. 初始化 dp[0]=0; dp[2]=1
  4. 遍历顺序:

伪代码(C++)

 

python代码

class Solution:
         # 假设对正整数 i 拆分出的第一个正整数是 j(1 <= j < i),则有以下两种方案:
        # 1) 将 i 拆分成 j 和 i−j 的和,且 i−j 不再拆分成多个正整数,此时的乘积是 j * (i-j)
        # 2) 将 i 拆分成 j 和 i−j 的和,且 i−j 继续拆分成多个正整数,此时的乘积是 j * dp[i-j]
    def integerBreak(self, n):
        dp = [0] * (n + 1)   # 创建一个大小为n+1的数组来存储计算结果
        dp[2] = 1  # 初始化dp[2]为1,因为当n=2时,只有一个切割方式1+1=2,乘积为1
       
        # 从3开始计算,直到n
        for i in range(3, n + 1):
            # 遍历所有可能的切割点
            for j in range(1, i // 2 + 1):

                # 计算切割点j和剩余部分(i-j)的乘积,并与之前的结果进行比较取较大值
                
                dp[i] = max(dp[i], (i - j) * j, dp[i - j] * j)
        
        return dp[n]  # 返回最终的计算结果

96.不同的二叉搜索树 跳过

leetcode题目链接
代码随想录文档讲解

思路

相当于爬楼梯题目的消费版

  1. dp数组的含义,到达i位置的花费为dp[i]
  2. dp[i]可由dp[i-1]跳1步或者dp[i-2]跳2步:dp[i] = min(dp[i-1] + cost[i-1] , dp[i-2] + cost[i-2])
  3. 初始化:dp[0]=0, dp[1]=0
  4. 每一个都是由前两个数组求得的,往前求

伪代码(C++)


python代码

class Solution:
    def minCostClimbingStairs(self, cost: List[int]) -> int:
        dp = [0] * (len(cost)+1)
        for i in range(2, len(cost)+1): 
            dp[i] = min(dp[i-1] + cost[i-1], dp[i-2]+cost[i-2])
        return dp[len(cost)]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值