题目描述:
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。
例如,给定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
说明:
如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。
思路:
- 整体思路是动态规划
- 首先新建一个二维数组,初始化值全为0;
- 三个关键的关系式,状态方程
- 核心代码:
for (int i = 1; i < n; ++i) {
dp[i][0] = dp[i-1][0] + triangle.get(i).get(0);
for (int j = 1; j < i; ++j) {
dp[i][j] = Math.min(dp[i-1][j-1], dp[i-1][j]) + triangle.get(i).get(j);
}
dp[i][i] = dp[i-1][i-1] + triangle.get(i).get(i);
}
完整代码:
public class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
int n = triangle.size();
int[][] dp = new int[n][n]; // 初始值全为0
dp[0][0] = triangle.get(0).get(0);
for (int i = 1; i < n; +Solution+i) {
dp[i][0] = dp[i-1][0] + triangle.get(i).get(0); // 处理边缘值
for (int j = 1; j < i; ++j) {
dp[i][j] = Math.min(dp[i-1][j-1], dp[i-1][j]) + triangle.get(i).get(j); // 核心状态方程
}
dp[i][i] = dp[i-1][i-1] + triangle.get(i).get(i); // 处理边缘值
}
int minTotal = dp[n - 1][0];
for (int i = 1; i < n; ++i) {
minTotal = Math.min(minTotal, dp[n - 1][i]); //寻找最后一行dp[][]的最小值
}
return minTotal;
}
public static void main(String[] args) {
Solution sol = new Solution();
List<List<Integer>> list = new ArrayList<List<Integer>>(); // 二维 ArrayList
list.add(Arrays.asList(2));
list.add(Arrays.asList(3,4));
list.add(Arrays.asList(6,5,7));
list.add(Arrays.asList(4,1,8,3));
int minNum = sol.minimumTotal(list);
System.out.println(minNum);
}
}