LeetCode 64 Minimum Path Sum
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.
Note: You can only move either down or right at any point in time.
DifficultyMedium
Similar Problems
[LeetCode 63] Unique Paths II M
[LeetCode 174] Dungeon Game H
Problem: Minimum Cost Path (MCP)
Given a cost matrix cost[][]
and a position (m, n)
in cost[][]
, write a function that returns the minimum cost of path from (0, 0) to (m, n).
Total cost of a path to (m, n) is sum of all the costs on that path (including both source and destination).
You can only traverse down
, right
and diagonally lower
cells from a given cell,
i.e., from a given cell (i, j), cells (i+1, j), (i, j+1) and (i+1, j+1) can be traversed.
You may assume that all costs are positive integers.
Extensions
(1) Maximum Path Sum
(2) Dual Min Path Sum (double line dp)
If two people starting out from the top-left corner at the same time, towarding to the right-bottom corner,
if the paths of the people have walked through can not have intersection (the never walk through the same point in between),
what would be the max distance the two path have?
(3) Same problem with the (2), one person take a round trip from top-left to bottom-right, and back from bottom-right to top-left, the max distance of this round trip?
Analysis
A classic dp problem.
Let dp[i][j]
represent the minimum total cost of path from top-left corner to grid[i][j]
.
then we have dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1])
.
Be careful with the boundary condition:
the first row and first column. e.g. dp[i-1][j]
.
If we start the index from i = 0, then
dp[i-1][j]
will have negative indexdp[-1][j]
, which is wrong.
We can letdp[i][j]
do represent the minimum cost of path from(0, 0)
togrid[i-1][j-1]
. Then we start index fromi = 1, j = 1
, thusdp[m][n]
should be the answer. Since we need to usedp[m][n]
we have to declare the 2-D array the size of m+1 and n+1. Also,grid[i-1][j-1]
is the position we are processing.Inital value, since
dp[0][j]
anddp[i][0]
does not any meaning in our case(we only to use it to avoid overflow.
Improvement
Since dp[i][j]
has only thing to do with the previous dp[i-1][j]
and dp[i][j-1]
,
we can reduce the 2-d array to 1-d array, using rolling array to reduce space usage.
Solutions
- DP with 2D Array
class Solution {
public:
int minPathSum(vector<vector<int>> &grid) {
int row = grid.size(), col;
if(row == 0) return 0;
else col = grid[0].size();
vector<vector<int>> dp(row + 1, vector<int>(col + 1, INT_MAX));
dp[0][1] = 0;
for(int i = 1; i <= row; i++)
for(int j = 1; j <= col; j++)
dp[i][j] = grid[i - 1][j - 1] + min(dp[i][j - 1], dp[i - 1][j]);
return dp[row][col];
}
};
- DP with 1D Array
class Solution {
public:
int minPathSum(vector<vector<int>> &grid) {
int row = grid.size(), col;
if(row == 0) return 0;
else col = grid[0].size();
vector<int> dp(col + 1, INT_MAX);
dp[1] = 0;
for(int i = 1; i <= row; i++)
for(int j = 1; j <= col; j++)
dp[j] = grid[i - 1][j - 1] + min(dp[j], dp[j - 1]);
return dp[col];
}
};
- DP In Place
class Solution{
public:
int miniPathSum(vector<vector<int>> &grid){
int m = grid.size();
int n = grid[0].size();
for(int i = 0; i < m; ++i){
for(int j = 0; j < n; ++j){
if(i == 0){
if(j == 0) grid[i][j] = grid[i][j];
else grid[i][j]= grid[i][j - 1] + grid[i][j];
}
else if(j == 0) grid[i][j] = grid[i][i-1][j] + grid[i][j];
else grid[i][j] = min(grid[i-1][j], grid[i][j-1]) + grid[i][j];
}
}
return grid[m - 1][n -1];
}
};
- Golang Solution (1D Array)
func minPathSum(grid [][]int) int {
m := len(grid)
if m == 0 {
return 0
}
n := len(grid[0])
dp := make([]int, n+1)
for i := 0; i <= n; i++ {
dp[i] = MaxInt
}
dp[1] = 0
for i := 1; i <= m; i++ {
for j := 1; j <= n; j++ {
dp[j] = grid[i-1][j-1] + min(dp[j], dp[j-1])
}
fmt.Println(dp)
}
return dp[n]
}
const MaxUint = ^uint(0) // should be 1111-1111
const MaxInt = int(MaxUint >> 1) // should be 0111-1111
func min(a, b int) int {
if a <= b {
return a
}
return b
}