给定一个包含非负整数的 m x n
网格 grid
,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例 1:
输入:grid = [[1,3,1],[1,5,1],[4,2,1]] 输出:7 解释:因为路径 1→3→1→1→1 的总和最小。
示例 2:
输入:grid = [[1,2,3],[4,5,6]] 输出:12
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 200
0 <= grid[i][j] <= 200
思路,背包算法,创建数组a[200][200]={0}.首先初始化边界,因为只能向下或者向右走;
所以可以把第一行和第一列直接初始化,第一行初始化
a[0][i]=a[0][i-1]+grid[0][i] ;
以第一个示例为例子:第一行为1,4,5
第一列初始化:
a[j][0]=a[j-1][0]+grid[j][0];
1,2,6
然后两层循环遍历,起点都是1,因为0,也就是第一列和第一行已经初始化过了。
所以是从a[1][1]开始,有两种可能,第一种是[0][1]方向走过来,第二种是[1][0]方向走过来。
题目要求是最小。所以可以使用三目操作符
a[1][1 ]= a[0][1]+grid[1][1]>a[1][0]+grid[1][1]?a[1][0]+grid[1][1]:a[0][1]+grid[1][1];
1 | 4 | 5 |
2 | 7 | 0 |
6 | 0 | 0 |
2+5<4+5所以为7;
以此类推,最后只要返回第一个元素的对角即可;
但是这样很浪费空间,可以利用传过来的数组,直接原地赋值。
时间复杂度还是O(n)
空间复杂度则变为O(1)
int minPathSum(int** grid, int gridSize, int* gridColSize) {
for(int j=1;j<gridColSize[0];j++)//初始化第一行
{
grid[0][j]=grid[0][j-1]+grid[0][j];
}
for(int i=1;i<gridSize;i++)//初始化第一列
{
grid[i][0]=grid[i-1][0]+grid[i][0];
}
for(int i=1;i<gridSize;i++)//循环操作
{
for(int j=1;j<gridColSize[i];j++)
{
grid[i][j]=grid[i][j-1]+grid[i][j]>grid[i-1][j]+grid[i][j]?grid[i-1][j]+grid[i][j]:grid[i][j-1]+grid[i][j];//赋值花费小的
}
}
return grid[gridSize-1][gridColSize[gridSize-1]-1];//返回终点的值
}