题目描述
给出一个三角形,计算从三角形顶部到底部的最小路径和,每一步都可以移动到下面一行相邻的数字,
例如,给出的三角形如下:
[↵ [2],↵ [3,4],↵ [6,5,7],↵ [4,1,8,3]↵]
最小的从顶部到底部的路径和是2 + 3 + 5 + 1 = 11。
注意:
如果你能只用O(N)的额外的空间来完成这项工作的话,就可以得到附加分,其中N是三角形中的行总数。
分析
典型的动态规划的题目,三角形往上、往下算都可以,下一层某一结点的最小值等于上一层与它成三角关系的两个结点的较小的值加上它本身。选择从下往上算,原因是上一层比下一层含有的数字少一个,这样它下面的两个角都存在。倒数第二层开始赋值将它加上下面更小的数,以此类推,直到算到第一行。
时间复杂度
O(n^2)
空间复杂度为0版本–直接修改上面的值
import java.util.ArrayList;
public class Solution {
public int minimumTotal(ArrayList<ArrayList<Integer>> triangle) {
// [2], [2],
// [3,4], [3, 4], [2],
// [6,5,7], ==> [7, 6, 10] ==> [9, 10] ==> [11]
// [4,1,8,3]
//从下往上找,修改该位置的值为它本身加上下面两个角上较小的一个
int rows=triangle.size();
int min = 0;
for(int i = rows-2; i>=0 ; i--){
for(int j = 0; j < triangle.get(i).size(); j++){
min = Math.min(triangle.get(i+1).get(j), triangle.get(i+1).get(j+1));
triangle.get(i).set( j, triangle.get(i).get(j) + min);
}
}
return triangle.get(0).get(0);
空间复杂度为O(n)版本,一个大小为n的数组记录当前修改的行
import java.util.ArrayList;
public class Solution {
public int minimumTotal(ArrayList<ArrayList<Integer>> triangle) {
// [2], [2],
// [3,4], [3, 4], [2],
// [6,5,7], ==> [7, 6, 10] ==> [9, 10] ==> [11]
// [4,1,8,3]
//从下往上找,修改该位置的值为它本身加上下面两个角上较小的一个
int rows=triangle.size();
int min = 0;
int [] res = new int[rows];
//先把最后一层的记录下来
for(int i = 0; i < rows; i++)
res[i] = triangle.get(rows-1).get(i);
for(int i = rows-2; i>=0 ; i--){
for(int j = 0; j < triangle.get(i).size(); j++){
min = Math.min(res[j], res[j+1]);
res[j] = triangle.get(i).get(j) + min;
}
}
return res[0];
}
}