链接:https://leetcode-cn.com/problems/minimum-path-sum/
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
二、题解
根据题意,我们需要找到从左上角到右下角的最小路径和,同时每次只能向下或者向右移动一步。
定义数组元素的含义
dp[i][j]含义:当从左上角走到 (i,j) 位置时,最小路径和为 dp[i][j]
定义二维数据 dp[i][j],数组是从下标 0 开始算起的,所以右下角的位置是 (m-1,n-1),所以 dp[m-1][n-1] 就是我们所求。
找到数组的递推关系式
如何才能到达 (i,j) 这个位置?由于可以向下走或者向右走,所以有两种方式到达:
因为我们需要找的不是 m x n 网格所有路径,而是寻找所有路径中,路径和最小的那一条。
所以:dp[i][j]=min(dp[i-1][j],dp[i][j-1])+arr[i][j]
找到初始值
当 dp[i][j] 中,如果 i 或者 j 有一个为 0,那么还能使用关系式吗?
当然是不能的,因为如果 i 或者 j 有一个为 0,此时 i - 1 或者 j - 1 就是负数,数组就会有问题。所以我们的初始值是计算出所有的 dp[0][0….n-1] 和所有的 dp[0….m-1][0]
时间复杂度:O(m*n)
空间复杂度:O(m*n)
Python:
class Solution:
def minPathSum(self, grid: List[List[int]]) -> int:
m=len(grid) # 行
n=len(grid[0]) # 列
if m<=0 or n<=0:
return 0
dp=[ n*[_] for _ in range(m)]
dp[0][0]=grid[0][0]
for i in range(1,m):
dp[i][0]=dp[i-1][0]+grid[i][0]
for i in range(1,n):
dp[0][i]=dp[0][i-1]+grid[0][i]
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]
return dp[m-1][n-1]
Go:
func minPathSum(grid [][]int) int {
if len(grid) == 0 || len(grid[0]) ==0{
return 0
}
m,n:=len(grid),len(grid[0])
dp:=make([][]int,m)
for i:=0;i<m;i++{
dp[i]=make([]int,n)
}
dp[0][0]=grid[0][0]
for i:=1;i<m;i++{
dp[i][0]=dp[i-1][0]+grid[i][0]
}
for j:=1;j<n;j++{
dp[0][j]=dp[0][j-1]+grid[0][j]
}
for i:=1;i<m;i++{
for j:=1;j<n;j++{
dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j]
}
}
return dp[m-1][n-1]
}
func min(x,y int) int{
if x<y{
return x
}
return y
}
如果觉得文章不错,希望大家可以扫描上方名片关注我的微信公众号噢,点赞、收藏、在看、分享就再好不过了。如果有任何建议和问题,可以在下方给我留言,我会及时回复的,同时会不定期更新更多的文章,祝我们终将自由。