64. Minimum Path Sum

Dynamic Programming

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Solution {
public int minPathSum(int[][] grid) {
int m = grid.length;
int n = grid[0].length;

int[][] dp = new int[m][n];

// update the first row and column
for (int i = 0; i < m; i++) {
if (i == 0) {
dp[i][0] = grid[0][0];
} else {
dp[i][0] = dp[i-1][0] + grid[i][0];
}
}

for (int j = 0; j < n; j++) {
if (j == 0) {
dp[0][j] = grid[0][0];
} else {
dp[0][j] = dp[0][j-1] + grid[0][j];
}
}

// calculate from (1,1)
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = Math.min(dp[i-1][j] + grid[i][j], dp[i][j-1] + grid[i][j]);
}
}

return dp[m-1][n-1];

}
}

Remarks:

  1. Adapted from No. 62.
  2. TC: $O(m\times n)$, SC: $O(m\times n)$.

DP with pruning (top-buttom)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
public int minPathSum(int[][] grid) {
int m = grid.length;
int n = grid[0].length;

int[][] dp = new int[m][n];
for (int[] row : dp) {
Arrays.fill(row, -1);
}

return rec(m - 1, n - 1, grid, dp);
}

private int rec(int i, int j, int[][] grid, int[][] dp) {
if (i < 0 || j < 0) {
return Integer.MAX_VALUE; // out of range
}

if (i == 0 && j == 0) {
return grid[0][0]; // start
}

if (dp[i][j] != -1) {
return dp[i][j]; // memorize
}

int left = rec(i, j - 1, grid, dp);
int up = rec(i - 1, j, grid, dp);

dp[i][j] = grid[i][j] + Math.min(left, up);
return dp[i][j];
}
}

Remarks:

  1. TC: $O(m\times n)$, SC: $O(m\times n)$.
  2. Pruning: only calculate the blocks that are required to find the minimum path. Larger stack usage.