代码随想录算法训练营第三十三天|62.不同路径 63. 不同路径 II 343. 整数拆分 96.不同的二叉搜索树
62.不同路径
感觉这里已经是二维动态规划了,思路是一样的,五步走,先试试
class Solution:def uniquePaths(self, m: int, n: int) -> int:dp = [[0] * (n + 1) for _ in range(m + 1)]dp[1][1]=1for i in range(1,m+1):for j in range(1,n+1):if i==j==1:continuedp[i][j] = dp[i-1][j]+dp[i][j-1]return dp[m][n]
解析的方法更好,直接把第一列和第一行初始化为1,然后就少了很多
class Solution:def uniquePaths(self, m: int, n: int) -> int:# 创建一个二维列表用于存储唯一路径数dp = [[0] * n for _ in range(m)]# 设置第一行和第一列的基本情况for i in range(m):dp[i][0] = 1for j in range(n):dp[0][j] = 1# 计算每个单元格的唯一路径数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
相比于原来,其实就是多了对于障碍物的处理,一旦遇到障碍物体就把当前的dp数组值设置为0就可以了
class Solution:def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:m = len(obstacleGrid)n = len(obstacleGrid[0])dp = [[0]*n for _ in range(m)]if obstacleGrid[0][0]==1:return 0dp[0][0]=1for i in range(1,n):if obstacleGrid[0][i]==1:dp[0][i]=0else:dp[0][i]=dp[0][i-1]for i in range(1,m):if obstacleGrid[i][0]==1:dp[i][0]=0else:dp[i][0]=dp[i-1][0]#print(dp)for i in range(1,m):for j in range(1,n):if obstacleGrid[i][j]==1:dp[i][j]=0else:dp[i][j] = dp[i-1][j]+dp[i][j-1]return dp[m-1][n-1]
343. 整数拆分
感觉这个题目,不知道dp数组应该表示什么,假设表示最大的乘积,我又想不到状态转移方程应该是什么
class Solution:def integerBreak(self, n: int) -> int:dp = [0]*(n+1)dp[2]=1for i in range(3,n+1):for j in range(1,i-1):dp[i] = max(dp[i],j*(i-j),j*dp[i-j])print(dp[i])return dp[n]
我没太搞懂的地方是,为什么在比较的时候,还要加上本身比较,奥,现在想到了,因为如果不包含本身的话,后面在比较的时候,会把前面找到的最大的值给丢掉
96.不同的二叉搜索树
这个想不出递推关系,多一个节点会比之前的二叉树多什么,这个递归关系很巧妙,利用的是左右子树的节点数量问题
dp[i] = dp[0]*dp[i-1]+dp[1]*dp[i-2]+...+dp[i-1]dp[0]
初始化,dp[0]=1,dp[1]=1
class Solution:def numTrees(self, n: int) -> int:dp= [0]*(n+1)dp[0],dp[1]=1,1for i in range(2,n+1):for j in range(i):dp[i]+=dp[j]*dp[i-j-1]return dp[n]