代码随想录NO37 |动态规划 62.不同路径 63. 不同路径 II
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
动态规划 62.不同路径 63. 不同路径 II
今天是动态规划第二天的题了就两道题算是二刷
一个机器人位于一个 m x n 网格的左上角 起始点在下图中标记为 “Start” 。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角在下图中标记为 “Finish” 。
问总共有多少条不同的路径
机器人从(0 , 0) 位置出发到(m - 1, n - 1)终点。
按照动规五部曲来分析
- 确定dp数组dp table以及下标的含义
dp[i][j] 表示从0 0出发到(i, j) 有dp[i][j]条不同的路径。 - 确定递推公式
想要求dp[i][j]只能有两个方向来推导出来即dp[i - 1][j] 和 dp[i][j - 1]。
此时在回顾一下 dp[i - 1][j] 表示啥是从(0, 0)的位置到(i - 1, j)有几条路径dp[i][j - 1]同理。
那么很自然dp[i][j] = dp[i - 1][j] + dp[i][j - 1]因为dp[i][j]只有这两个方向过来。 - dp数组的初始化
如何初始化呢首先dp[i][0]一定都是1因为从(0, 0)的位置到(i, 0)的路径只有一条那么dp[0][j]也同理。 - 确定遍历顺序
这里要看一下递推公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1]dp[i][j]都是从其上方和左方推导而来那么从左到右一层一层遍历就可以了。
这样就可以保证推导dp[i][j]的时候dp[i - 1][j] 和 dp[i][j - 1]一定是有数值的。 - 举例推导dp数组
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
# 初始化保存状态的二维矩阵
dp = [[1 for i in range(n)] for j in range(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]
不同初始化二维矩阵
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
# 初始化保存状态的二维矩阵
dp = [[0 for i in range(n)] for j in range(m)]
for i in range(m): dp[i][0] = 1
for 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数组dp table以及下标的含义
dp[i][j] 表示从0 0出发到(i, j) 有dp[i][j]条不同的路径。 - 确定递推公式
递推公式和62.不同路径一样dp[i][j] = dp[i - 1][j] + dp[i][j - 1]。
但这里需要注意一点因为有了障碍(i, j)如果就是障碍的话应该就保持初始状态初始状态为0。 - dp数组如何初始化
因为从(0, 0)的位置到(i, 0)的路径只有一条所以dp[i][0]一定为1dp[0][j]也同理。
但如果(i, 0) 这条边有了障碍之后障碍之后包括障碍都是走不到的位置了所以障碍之后的dp[i][0]应该还是初始值0。 - 确定遍历顺序
从递归公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 中可以看出一定是从左到右一层一层遍历这样保证推导dp[i][j]的时候dp[i - 1][j] 和 dp[i][j - 1]一定是有数值。 - 举例推导dp数组
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
m = len(obstacleGrid)
n = len(obstacleGrid[0])
dp = [[0 for _ in range(n)] for _ in range(m)]
for i in range(m):
if obstacleGrid[i][0] == 1:
break
dp[i][0] = 1
for i in range(n):
if obstacleGrid[0][i] == 1:
break
dp[0][i] = 1
if obstacleGrid[0][0] == 1 or obstacleGrid[m-1][n-1] == 1: return 0
for i in range(1,m):
for j in range(1,n):
if obstacleGrid[i][j] == 1: continue
dp[i][j] = dp[i-1][j] + dp[i][j-1]
return dp[m-1][n-1]
今天两道题不算难但是第二道题还是第一次看完题解写出来之前都是囫囵吞枣还是理解清楚了再去独立写代码坚决不能复制粘贴