代码随想录算法训练营-动态规划-2|62. 不同路径、63. 不同路径 II、343. 整数拆分、96. 不同的二叉搜索树
62. 不同路径
1 class Solution: 2 def uniquePaths(self, m: int, n: int) -> int: 3 # 创建一个二维列表用于存储唯一路径数 4 dp = [[0] * n for _ in range(m)] 5 6 # 设置第一行和第一列的基本情况 7 for i in range(m): 8 dp[i][0] = 1 9 for j in range(n): 10 dp[0][j] = 1 11 12 # 计算每个单元格的唯一路径数 13 for i in range(1, m): 14 for j in range(1, n): 15 dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 16 17 # 返回右下角单元格的唯一路径数 18 return dp[m - 1][n - 1]
1 class Solution: 2 def uniquePathsWithObstacles(self, obstacleGrid): 3 m = len(obstacleGrid) 4 n = len(obstacleGrid[0]) 5 if obstacleGrid[m - 1][n - 1] == 1 or obstacleGrid[0][0] == 1: 6 return 0 7 dp = [[0] * n for _ in range(m)] 8 for i in range(m): 9 if obstacleGrid[i][0] == 0: # 遇到障碍物时,直接退出循环,后面默认都是0 10 dp[i][0] = 1 11 else: 12 break 13 for j in range(n): 14 if obstacleGrid[0][j] == 0: 15 dp[0][j] = 1 16 else: 17 break 18 for i in range(1, m): 19 for j in range(1, n): 20 if obstacleGrid[i][j] == 1: 21 continue 22 dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 23 return dp[m - 1][n - 1]
1 class Solution: 2 # 假设对正整数 i 拆分出的第一个正整数是 j(1 <= j < i),则有以下两种方案: 3 # 1) 将 i 拆分成 j 和 i−j 的和,且 i−j 不再拆分成多个正整数,此时的乘积是 j * (i-j) 4 # 2) 将 i 拆分成 j 和 i−j 的和,且 i−j 继续拆分成多个正整数,此时的乘积是 j * dp[i-j] 5 def integerBreak(self, n): 6 dp = [0] * (n + 1) # 创建一个大小为n+1的数组来存储计算结果 7 dp[2] = 1 # 初始化dp[2]为1,因为当n=2时,只有一个切割方式1+1=2,乘积为1 8 9 # 从3开始计算,直到n 10 for i in range(3, n + 1): 11 # 遍历所有可能的切割点 12 for j in range(1, i // 2 + 1): 13 14 # 计算切割点j和剩余部分(i-j)的乘积,并与之前的结果进行比较取较大值 15 16 dp[i] = max(dp[i], (i - j) * j, dp[i - j] * j) 17 18 return dp[n] # 返回最终的计算结果
1 class Solution: 2 def numTrees(self, n: int) -> int: 3 dp = [0] * (n + 1) # 创建一个长度为n+1的数组,初始化为0 4 dp[0] = 1 # 当n为0时,只有一种情况,即空树,所以dp[0] = 1 5 for i in range(1, n + 1): # 遍历从1到n的每个数字 6 for j in range(1, i + 1): # 对于每个数字i,计算以i为根节点的二叉搜索树的数量 7 dp[i] += dp[j - 1] * dp[i - j] # 利用动态规划的思想,累加左子树和右子树的组合数量 8 return dp[n] # 返回以1到n为节点的二叉搜索树的总数量