解法一:动态规划

dp[i][j] 表示到达 (i, j) 时的最小路径和,则有以下状态转移方程:
120. 三角形最小路径和 - 图1

  1. import java.util.Arrays;
  2. import java.util.List;
  3. class Solution {
  4. public int minimumTotal(List<List<Integer>> triangle) {
  5. final int depth = triangle.size();
  6. // dp[i][j]表示到达(i, j)时的最小路径和
  7. int[][] dp = new int[depth][depth];
  8. dp[0][0] = triangle.get(0).get(0);
  9. for (int i = 1; i < depth; ++i) {
  10. // 行首和行尾单独处理
  11. dp[i][0] = dp[i - 1][0] + triangle.get(i).get(0);
  12. for (int j = 1; j < i; ++j) {
  13. dp[i][j] = Math.min(dp[i - 1][j - 1], dp[i - 1][j]) + triangle.get(i).get(j);
  14. }
  15. dp[i][i] = dp[i - 1][i - 1] + triangle.get(i).get(i);
  16. }
  17. int ans = Integer.MAX_VALUE;
  18. for (int i : dp[depth - 1]) {
  19. ans = Math.min(ans, i);
  20. }
  21. return ans;
  22. }
  23. }

解法二:动态规划

有了第一种做法,可以发现每次计算当前层时只用到了上一层的结果,因此在空间使用上可以进行压缩,改用一维数组来存储。要注意这时更新结果要倒序进行,否则部分上一层待使用的结果会被下一层的的新数据代替。当然也可以用两个数组分别存储上一层和当前层的结果,每计算完一层就更新,这样就可以不用考虑顺序的问题。

  1. import java.util.Arrays;
  2. import java.util.List;
  3. class Solution {
  4. public int minimumTotal(List<List<Integer>> triangle) {
  5. final int depth = triangle.size();
  6. // dp[i]表示到达当前层第i格时的最小路径和
  7. int[] dp = new int[depth];
  8. dp[0] = triangle.get(0).get(0);
  9. for (int i = 1; i < depth; ++i) {
  10. // 倒序更新每一格
  11. // 这样前面的格子更新时依然使用上一层的结果, 不会受到影响
  12. dp[i] = dp[i - 1] + triangle.get(i).get(i);
  13. for (int j = i - 1; j > 0; --j) {
  14. dp[j] = Math.min(dp[j - 1], dp[j]) + triangle.get(i).get(j);
  15. }
  16. dp[0] = dp[0] + triangle.get(i).get(0);
  17. }
  18. int ans = Integer.MAX_VALUE;
  19. for (int i : dp) {
  20. ans = Math.min(ans, i);
  21. }
  22. return ans;
  23. }
  24. }