Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
For example, given the following triangle
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
The minimum path sum from top to bottom is 11
(i.e., 2 + 3 + 5 + 1 = 11).
Note:
Bonus point if you are able to do this using only O(n) extra space, wheren is the total number of rows in the triangle.
思路1: 记忆化搜索,注意首先赋值为Integer.MAX_VALUE; 然后判断有没有访问过;
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
int m = triangle.size();
int n = triangle.get(m - 1).size();
int[][] cache = new int[m][n];
for(int i = 0; i < m; i++) {
Arrays.fill(cache[i], Integer.MAX_VALUE);
}
return dfs(triangle, 0, 0, cache);
}
private int dfs(List<List<Integer>> A, int x, int y, int[][] cache) {
int m = A.size();
int n = A.get(m - 1).size();
if(x >= m || y >= n) {
return 0;
}
if(cache[x][y] != Integer.MAX_VALUE) {
return cache[x][y];
}
cache[x][y] = A.get(x).get(y) + Math.min(dfs(A, x + 1, y, cache),
dfs(A, x + 1, y + 1, cache));
return cache[x][y];
}
}
思路2:用标准的dp的方法来做,从下往上计算;递推公式dp[i][j] = Math.min( dp[i+1][j] , dp[i+1][j+1] ) + triangle[i][j]; 初始化最后一行,然后往上计算。这次也是beat 91.6% submission,记忆化搜索跟动态规划是等价的。使用滚动数组,优化空间,N*N的矩阵,只用最后两行,2*N的数组就可以完成,就是算完一个给另外一个,相互赋值;牛逼的方法是,所有的row坐标 % 2, 滚动数组,从row开始循环,就是row % 2,从col开始循环就是col % 2, 另外initial的时候也要% 2;
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
int m = triangle.size();
int n = triangle.get(m - 1).size();
int[][] dp = new int[m][n];
// initial last row;
for(int j = 0; j < n; j++) {
dp[m - 1][j] = triangle.get(m - 1).get(j);
}
// calculate from bottom to top;
for(int i = m - 2; i >= 0; i--) {
// 注意这里不能用n,只能每行每行的算size,因为有短小的,会有NPE;
for(int j = 0; j < triangle.get(i).size(); j++) {
dp[i][j] = triangle.get(i).get(j) + Math.min(dp[i + 1][j], dp[i + 1][j + 1]);
}
}
return dp[0][0];
}
}
滚动数组,Space 优化到O(m);
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
int m = triangle.size();
int n = triangle.get(m - 1).size();
int[][] dp = new int[2][n];
// initial last row;
for(int j = 0; j < n; j++) {
dp[(m - 1) % 2][j] = triangle.get(m - 1).get(j);
}
// calculate from bottom to top;
for(int i = m - 2; i >= 0; i--) {
// 注意这里不能用n,只能每行每行的算size,因为有短小的,会有NPE;
for(int j = 0; j < triangle.get(i).size(); j++) {
dp[i % 2][j] = triangle.get(i).get(j) + Math.min(dp[(i + 1) % 2][j], dp[(i + 1) % 2][j + 1]);
}
}
return dp[0][0];
}
}