给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
1、题目分析
从左上角走到右下角,然后每次只能向下或者向右走一步,最后得到一条最短路径,很显然典型的动态规划问题。
2、解题分析
- 动态规划
- 初始化一个dp数组,和给定数组一样大小,dp[0][0]=grid[0][0]
- 初始化dp的第一行和第一列
- 双层循环更新dp数组,状态转移方程:dp[i][j] = min(dp[i-1][j],dp[i][j-1])+grid[i][j]
- 因为从两个方向来,所以比较两个方向的最小值
- 返回dp[-1][-1]得到最短路径
- 原地优化
- 上述动态规划的空间复杂度是O(m*n)
- 降低时间复杂度的话就再原地进行动态转移变换
3、代码
class Solution:
def minPathSum(self, grid: List[List[int]]) -> int:
if not grid:
return 0
m,n = len(grid),len(grid[0])
#初始化一个二维矩阵
dp = [[0]*n for _ in range(m)]
dp[0][0] = grid[0][0]
#初始化第一行和第一列
for i in range(1,n):
#dp[0][i] = grid[0][i]+dp[0][i-1]
grid[0][i]+=grid[0][i-1] #原地动态
for j in range(1,m):
#dp[j][0] += grid[j][0]+dp[j-1][0]
grid[j][0]+=grid[j-1][0] #原地动态
for i in range(1,m):
for j in range(1,n):
#dp[i][j] = min(dp[i-1][j],dp[i][j-1])+grid[i][j]
grid[i][j] += min(grid[i-1][j],grid[i][j-1]) #原地动态
return grid[-1][-1]
#return dp[-1][-1]
总结:看到最短路径等字眼,一般都想到BFS和动态规划;这道题目是一个典型的动态规划的问题。