返回 探索63:不同路径 II
进阶学习LeetCode —— 动态规划(六)
见解分享
2023-12-24 06:03:18
前言:动态规划的本质
动态规划是一种强大的算法范式,它善于解决具有重叠子问题和最优子结构特征的问题。在LeetCode 63题中,我们遇到的问题正是如此:从机器人出发,想要到达右下角,它有许多可能的路径,并且每条路径上的选择都会影响后续的可能性。如果我们使用暴力递归的方法,那么就会重复计算许多相同的子问题,导致时间复杂度呈指数级增长。
算法:动态规划解法
动态规划的思想是将问题分解成更小的子问题,并逐步求解这些子问题,最终得到整个问题的解。在LeetCode 63题中,我们可以将机器人从左上角到右下角的路径分为若干个子问题:从左上角到(1,0)、从左上角到(0,1)...从左上角到(m-1, n-1)。每个子问题的解都是基于其相邻子问题的解。
我们可以使用一个二维数组dp
来存储这些子问题的解。dp[i][j]
表示从左上角到(i, j)的路径数量。为了计算dp[i][j]
,我们需要考虑两个情况:
- 如果(i, j)存在障碍物,那么
dp[i][j]
为0。 - 如果(i, j)不存在障碍物,那么
dp[i][j]
等于从左上角到(i-1, j)的路径数量和从左上角到(i, j-1)的路径数量之和。
我们可以使用以下伪代码来动态规划的解法:
def uniquePathsWithObstacles(obstacleGrid):
m, n = len(obstacleGrid), len(obstacleGrid[0])
dp = [[0] * n for _ in range(m)]
dp[0][0] = 1 # 初始化左上角的路径数量为1
for i in range(m):
for j in range(n):
if obstacleGrid[i][j] == 1: # 如果存在障碍物,则路径数量为0
dp[i][j] = 0
elif i == 0 or j == 0: # 如果在第一行或第一列,则路径数量为1
dp[i][j] = 1
else:
dp[i][j] = dp[i-1][j] + dp[i][j-1] # 计算路径数量
return dp[m-1][n-1] # 返回从左上角到右下角的路径数量
复杂度分析
动态规划的解法的时间复杂度为O(mn),其中m和n分别是网格的行数和列数。空间复杂度也是O(mn),因为我们需要使用二维数组dp来存储子问题的解。
结语:算法的灵活性
动态规划是一种非常灵活的算法范式,它可以解决各种各样的问题。在LeetCode 63题中,我们使用动态规划来计算从左上角到右下角的不同路径数量。在其他问题中,我们可以使用动态规划来解决最长公共子序列、最短路径、最大子数组和等问题。
希望本文能够帮助您理解动态规划的思想和应用。如果您还有任何问题,欢迎随时提问。