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, where n is the total number of rows in the triangle.
分析:
又是最优化问题,想到DP。
接下来寻找子问题以及状态转移方程。
子问题一般分为两种:
1,从开头到 i ,并由 i 的最优解推出 i+1 的最优解,则表的最后一个元素最优解;
2,从 i 到结尾,并由 i+1 的最优解能够推出 i 的最优解,则表的第一个元素就是最优解。
(上面的表述不够严谨,也可能是根据 i-2, i-1, i 三个状态才能组合成 i+1的状态,大概意思哈)。
具体这个问题,子问题大概就应该按层数找吧。
假设按层数直接以 [0, i] 的最小路径和,没法由这个最优解推出[0, i+1] 的最优解,换成每个位置的最优解,则可以往下继续推。
我们先从从上向下来,
基本的思路是维持一个len 等于最后一行长度的数组array,初始为0.
则 array[ i ] = min{ array[i-1]+curr[i], array[i]+curr[i] }
用这种方法,需要注意两点:
1,注意i=0时,i-1的判断,否则数组下标要溢出;
2,每更新一层要从后向前来,因为如果从前往后来,更新了array[i] 在更新 array[i+1]的时候还要用原来的array[i]。
这样,到最后一层,遍历array数组找到最小值就是我们要的结果。
那么从下往上来呢?
思路还是维持一个len等于最后一行长度的数组array,这个初始值就要等于最后一行了。
则 array[ i ] = min{ curr[i]+array[i], curr[i]+array[i+1]}
最后,array[ 0 ]就是要的答案了。
感觉两种都行,下面是从下往上的代码。
public class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
if(triangle == null || triangle.size() == 0)
return 0;
int[] total = new int[triangle.size()];
for(int i=0; i<triangle.get(triangle.size()-1).size(); i++){
total[i] = triangle.get(triangle.size()-1).get(i);
}
for(int i=triangle.size()-2; i>=0; i--){
for(int j=0; j<triangle.get(i).size(); j++){
total[j] = triangle.get(i).get(j) + Math.min(total[j], total[j+1]);
}
}
return total[0];
}
}