描述
给定一个只含非负整数的m*n网格,找到一条从左上角到右下角的可以使数字和最小的路径。
Tip: 你在同一时间只能向下或者向右移动一步
样例
样例 1:
输入: [[1,3,1],[1,5,1],[4,2,1]]
输出: 7
样例解释:
路线为: 1 -> 3 -> 1 -> 1 -> 1。
样例 2:
输入: [[1,3,2]]
输出: 6
解释:
路线是: 1 -> 3 -> 2
解答
有两种方案可以实现:
- 采用递归,实现简单,但是数据大时性能弱。
- 采用广度优先搜索方式,性能较好。
class Solution {
public:
/**
* @param grid: a list of lists of integers
* @return: An integer, minimizes the sum of all numbers along its path
*/
int minPathSum(vector<vector<int>> &grid) {
// write your code here
if(grid.empty()){
return 0;
}
//return minPath(grid, 0, 0);
return minPath(grid);
}
// 递归方式搜索----数量大时,性能较弱。
int minPath(vector<vector<int>> &grid, int i, int j)
{
// 终点
if( i == grid.size() - 1 && j == grid[0].size() - 1)
{
// 输出路径表
return grid[i][j];
}
int nRight = 0x7FFFFFFF;
if(j + 1 < grid[0].size()){
// 将(i,j + 1)加入路径表
nRight = minPath(grid, i , j + 1);
// 将(i,j + 1)移出路径表
}
int nDown = 0x7FFFFFFF;
if(i + 1 < grid.size()){
// 将(i + 1,j)加入路径表
nDown = minPath(grid, i + 1, j);
// 将(i + 1,j)移出路径表
}
return std::min(nRight, nDown) + grid[i][j];
}
// 广度优先搜索
int minPath(vector<vector<int>> &grid)
{
int m = grid.size();
int n = grid[0].size();
// 构造两个临时容器
// arr用于存储当前点的最小路径和
// tmp用于存储当前点是否已被加入到队列
vector<vector<int>> arr = grid;
vector<vector<int>> tmp = grid;
// 赋值为均未加入到队列初始状态
for (int i = 0; i < m; i++)
{
for (int j = 0; j< n; j++)
{
tmp[i][j] = 0;
}
}
struct positon
{
int x;
int y;
};
std::queue<positon> p;
// 加入起点
p.push(positon{ 0, 0 });
tmp[0][0] = 1;
int nUp = 0;
int nLeft = 0;
while (p.size())
{
positon& frn = p.front();
// 从左边走过来的距离
if (frn.y > 0) {
nLeft = arr[frn.x][frn.y - 1];
}
else {
nLeft = 0x7FFFFFFF;
}
// 从上边走过来的距离
if (frn.x > 0) {
nUp = arr[frn.x - 1][frn.y];
}
else {
nUp = 0x7FFFFFFF;
}
// 取两者最小
if (nLeft != 0x7FFFFFFF || nUp != 0x7FFFFFFF) {
arr[frn.x][frn.y] = grid[frn.x][frn.y] + min(nLeft, nUp);
}
else {
arr[frn.x][frn.y] = grid[frn.x][frn.y];
}
// 右 下节点加入队列,若已被加入过,则不加入,否则指数型增长
if (frn.y < n - 1 && tmp[frn.x][frn.y + 1] != 1) {
tmp[frn.x][frn.y + 1] = 1;
p.push(positon{ frn.x, frn.y + 1 });
}
if (frn.x < m - 1 && tmp[frn.x + 1][frn.y] != 1) {
tmp[frn.x + 1][frn.y] = 1;
p.push(positon{ frn.x + 1, frn.y });
}
//队顶出队
p.pop();
}
return arr[m - 1][n - 1];
}
};