image.png
状态定义:dp[i][j] 表示到达 (i,j)处的最小路径和

问题目标:max(dp数组的最后一行的元素)

状态转移:这种题目有两种求解方式,自底向上和自顶向下。在这里采用的是自顶向下。同时说明一下,此处的三角形是以下三角的形式存储的。dp[i][j] = min(dp[i-1][j], dp[i-1][j-1]) + triangle[i][j]

状态初始化:j = 0 和 i == j 处是累加的

时间复杂度:O(m * n)

空间复杂度:O(m * n) ——可优化

原始代码

  1. class Solution {
  2. public int minimumTotal(List<List<Integer>> triangle) {
  3. int m = triangle.size();
  4. int n = triangle.get(m - 1).size();
  5. int[][] dp = new int[m][n];
  6. for(int i = 0; i < m; i++){
  7. for(int j = 0; j < n; j++){
  8. if(i < j){
  9. continue;
  10. }
  11. if(i == 0 && j == 0){
  12. dp[i][j] = triangle.get(i).get(j);
  13. continue;
  14. }
  15. if(j == 0){
  16. dp[i][j] = dp[i-1][j] + triangle.get(i).get(j);
  17. continue;
  18. }
  19. if(i == j){
  20. dp[i][j] = dp[i-1][j-1] + triangle.get(i).get(j);
  21. continue;
  22. }
  23. dp[i][j] = Math.min(dp[i-1][j], dp[i-1][j-1]) + triangle.get(i).get(j);
  24. }
  25. }
  26. int ans = dp[m-1][0];
  27. for(int i = 1; i < n; i++){
  28. ans = Math.min(ans, dp[m-1][i]);
  29. }
  30. return ans;
  31. }
  32. }

引入滚动数组优化空间复杂度,i & 1

  1. class Solution {
  2. public int minimumTotal(List<List<Integer>> triangle) {
  3. int m = triangle.size();
  4. int n = triangle.get(m - 1).size();
  5. int[][] dp = new int[2][n];
  6. dp[0][0] = triangle.get(0).get(0);
  7. for(int i = 1; i < m; i++){
  8. for(int j = 0; j <= i; j++){
  9. if(i == 0 && j == 0){
  10. dp[i & 1][j] = triangle.get(i).get(j);
  11. continue;
  12. }
  13. if(j == 0){
  14. dp[i & 1][j] = dp[(i - 1) & 1][j] + triangle.get(i).get(j);
  15. continue;
  16. }
  17. if(i == j){
  18. dp[i & 1][j] = dp[(i-1) & 1][j-1] + triangle.get(i).get(j);
  19. continue;
  20. }
  21. dp[i & 1][j] = Math.min(dp[(i - 1) & 1][j], dp[(i -1) & 1][j-1]) + triangle.get(i).get(j);
  22. }
  23. }
  24. int ans = dp[(m-1) & 1][0];
  25. for(int i = 1; i < n; i++){
  26. ans = Math.min(ans, dp[(m - 1) & 1][i]);
  27. }
  28. return ans;
  29. }
  30. }