题目描述:
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.
这个第一想法就是用dfs,然后用一个备忘录,dp[i,j]记录从(i, j)出发得到的最小总和。
代码如下:
public class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
int n=triangle.size();
int[][] dp=new int[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
dp[i][j]=Integer.MAX_VALUE;
}
}
return getMinimumTotal(triangle, 0, 0, dp);
}
public int getMinimumTotal(List<List<Integer>> triangle,int row,int col,int[][] dp){
if(row==triangle.size()-1){
int minimumTotal=triangle.get(row).get(col);
dp[row][col]=minimumTotal;
return minimumTotal;
}
int left=0,right=0;
if(dp[row+1][col]!=Integer.MAX_VALUE){
left=dp[row+1][col];
}else{
left=getMinimumTotal(triangle, row+1, col, dp);
}
if(dp[row+1][col+1]!=Integer.MAX_VALUE){
right=dp[row+1][col+1];
}else{
right=getMinimumTotal(triangle, row+1, col+1, dp);
}
int minimumTotal=left<right?triangle.get(row).get(col)+left:triangle.get(row).get(col)+right;
dp[row][col]=minimumTotal;
return minimumTotal;
}
}
但这个题要求用O(n)的内存空间。
设从[0, 0]出发,到[i, j]的最小总和为values[j],当到i+1行时,value[j]有三种情况:
if(j == 0){
values[j] = values[j] + cur.get(j);
}else if(j == cur.size()-1){
values[j] = values[j-1] + cur.get(j);
}else{
values[j] = (values[j] > values[j-1]? values[j-1]:values[j]) + cur.get(j);
}
要注意的是一定要从后往前遍历,这样才不会覆盖前面的数据、
代码如下:
public class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
if(triangle == null) return 0;
int len = triangle.size();
int[] values = new int[len]; //only O(n) extra space
values[0] = triangle.get(0).get(0);
for(int i=1; i<len; i++){
List<Integer> cur = triangle.get(i);
for(int j=cur.size()-1; j>=0; j--){
if(j == 0){
values[j] = values[j] + cur.get(j);
}else if(j == cur.size()-1){
values[j] = values[j-1] + cur.get(j);
}else{
values[j] = (values[j] > values[j-1]? values[j-1]:values[j]) + cur.get(j);
}
}
}
Arrays.sort(values);
return values[0];
}
}
下面的更简单也更容易理解,这个算法是从下往上遍历的:
public int minimumTotal(List<List<Integer>> triangle) {
int len = triangle.size();
int[] dp = new int[len];
for(int i = len-1;i >= 0; i--){
for(int j = 0; j <= i; j++){
if(i == len-1) dp[j]= triangle.get(i).get(j);
else{
dp[j] = Math.min(dp[j],dp[j+1])+triangle.get(i).get(j);
}
}
}
return dp[0];
}