题目
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/triangle
题目分析
贪心:失败(不是贪心题)
暴力搜索:失败(超时)
自顶向下:递归+记忆化(AC)
自底向上:有点dp味道(自身的状态转移)(AC)
我将着重分析第三,四个解法
递归的第一步画树状图
画完递归图后果然清晰多了
int row;
Integer[][]memo;
public int minimumTotal(List<List<Integer>> triangle) {
row = triangle.size();
memo = new Integer[row][row];
return helper(0,0, triangle);
}
/**
* 自顶向下记忆化搜索
* @param level 当前层次
* @param index 当前层次下标
* @param triangle 三角形
* @return
*/
private int helper(int level, int index, List<List<Integer>> triangle) {
//记忆化搜索直接返回
if(memo[level][index]!=null){
return memo[level][index];
}
//最后一层直接返回
if(level==row-1){
return memo[level][index]=triangle.get(level).get(index);
}
//不是最后一层的话,去找下一层,并返回当前层元素+下一层较小的元素
int left = helper(level+1,index,triangle);
int right = helper(level+1,index+1,triangle);
return memo[level][index]=triangle.get(level).get(index)+Math.min(left,right);
}
从上面解法明显可以感觉出这道题自顶向下实在是有点麻烦,要先走到底部再一层层弹回去顶层
如果采取自底向上则方便多了,甚至只需要o(1)的空间复杂度,但是提交的时候空间复杂度相比递归解法没有多大提升,这是我始终想不通的一点,可以评论区告诉我
/**
* 自底向上遍历
* @param triangle
* @return
*/
public int minimumTotal2(List<List<Integer>> triangle) {
int level = triangle.size()-1;//定位到最底层
while(level>0){//没有走到顶层 就一直循环
for(int i=0;i<level;i++){//遍历该层所有元素
//该层两两比较较小的出来
int min = Math.min(triangle.get(level).get(i),triangle.get(level).get(i+1));
//上一层的值
int r = triangle.get(level-1).get(i);
//更新上一层的值
triangle.get(level-1).set(i,r+min);
}
level--;
}
//返回顶层元素
return triangle.get(0).get(0);
}