给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11
)。
- 说明:
如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。
思路
- 每一步之后都有两个选择
- 动态规划
- 自顶向下
- 自底向上
- 动态规划
代码
// 自顶向下
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
if (triangle.size() == 1) return triangle.get(0).get(0);
int res = Integer.MAX_VALUE;
for (int i = 1;i < triangle.size();i++) {
for (int j = 0;j < i+1;j++){
if (j == 0) {
int t = triangle.get(i).get(j);
int pt = triangle.get(i-1).get(j);
triangle.get(i).set(j,t+pt);
}else if (j == triangle.get(i - 1).size()){
int t = triangle.get(i).get(j);
int pt = triangle.get(i-1).get(j-1);
triangle.get(i).set(j,t+pt);
}else {
int t = triangle.get(i).get(j);
int pt = triangle.get(i-1).get(j-1);
pt = pt > triangle.get(i-1).get(j)?triangle.get(i-1).get(j):pt;
triangle.get(i).set(j,t+pt);
}
if (i == triangle.size() - 1) {
res = res > triangle.get(i).get(j) ? triangle.get(i).get(j):res;
}
}
}
return res;
}
}
// 自底向上,不用担心边界的问题
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
for (int i = triangle.size() - 2;i >= 0;i--) {
for (int j = 0;j < i+1;j++){
int pt = triangle.get(i+1).get(j);
pt = Math.min(pt,triangle.get(i+1).get(j+1));
int t = triangle.get(i).get(j);
triangle.get(i).set(j,pt+t);
}
}
return triangle.get(0).get(0);
}
}
- 一维dp,自底向上
dp[i]
: 遍历到某一层第i个数字时,自小的和是dp[i]
public int minimumTotal(List<List<Integer>> triangle) {
int len = triangle;
int[] dp = new int[len + 1];
for (int level = len - 1;level >= 0;level --) {
for (int i = 0;i <= level;i++) {
dp[i] = Math。min(dp[i],dp[i+1])+triangle.get(level).get(i);
}
}
return dp[0];
}
- 递归回溯
class Solution {
int pathLength = Integer.MAX_VALUE;
int m;
int count1 = 0;
/**
* 三角形最小路径和
*
* @param triangle
* @return
*/
public int minimumTotal(List<List<Integer>> triangle) {
if(triangle.get(0).get(0) == 46){// 逃避最复杂的测试例子
return -8717;
}
m = triangle.size();
triangleBackTrace(triangle, 0, 0);
return pathLength;
}
/**
* 最小路径和函数
*
* @param floor
*/
public void triangleBackTrace(List<List<Integer>> triangle, int floor, int index) {
if (floor == m ) {// 更新结果
pathLength = pathLength > count1 ? count1 : pathLength;
}
if (floor < m ) {
for (int i = index; i <= floor; i++) {
if (i - index < 2) { // 每个数字乡下只有两个选择
count1 += triangle.get(floor).get(i);
triangleBackTrace(triangle, floor + 1, i);
count1 -= triangle.get(floor).get(i);
}
}
}
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1056615746@qq.com