0%

leetcode每日一题-三角形最小路径和

三角形最小路径和

image1

我们记dp[i][j]为在第i行第j列处元素的路径和,注意到三角形第i行有i个元素(i从1开始,在数组中下标为[0,n-1])。我们可以得到如下动态转移方程:

  1. $j$等于0,此时当前元素的路径和只能从上一行的最左边得到:

$$
dp[i][0] = dp[i-1][0] + c[i][0]
$$

  1. $j$等于$i$,此时当前元素的路径和只能从上一行的最右边得到:
    $$
    dp[i][i] = dp[i-1][i-1] + c[i][i]
    $$
  1. 其他情况,此时可以从上一行的两个元素处得到:
    $$
    dp[i][j] = min(dp[i-1][j],dp[i-1][j-1])+c[i][j]
    $$

$c[i][j]$表示在$(i,j)$处的元素值。

1
class Solution {
2
    public int minimumTotal(List<List<Integer>> triangle) {
3
        int n = triangle.size();
4
        int[][] dp = new int[n][n];
5
        dp[0][0] = triangle.get(0).get(0);
6
        for(int i=1; i<n; i++){
7
            dp[i][0] = dp[i-1][0] + triangle.get(i).get(0);
8
            for(int j=1; j<i; j++){
9
                dp[i][j] = Math.min(dp[i-1][j-1], dp[i-1][j]) + triangle.get(i).get(j);
10
            }
11
            dp[i][i] = dp[i-1][i-1] + triangle.get(i).get(i);
12
        }
13
        int ans = dp[n-1][0];
14
        for(int i=1; i<n; i++){
15
            ans = Math.min(ans, dp[n-1][i]);
16
        }
17
        return ans;
18
19
    }
20
}

复杂度分析

  • 时间复杂度:$O(n^2)$。
  • 空间复杂度:$O(n^2)$。

如果想进一步优化空间复杂度到$O(n)$,需要使用滚动数组,因为观察转移方程$dp[i][j]$的状态只与$dp[i-1][j-1]$和$dp[i-1][j]$有关。如果遍历$j$的时候从$i-1$到$0$遍历,那么只需要一个一维数组即可。如果$j$遍历是正序遍历,那么就会破坏第$i-1$行处$j-1$的值,如果是逆序的话就正好不会破坏。

1
class Solution {
2
    public int minimumTotal(List<List<Integer>> triangle) {
3
        int n = triangle.size();
4
        int[] dp = new int[n];
5
        dp[0] = triangle.get(0).get(0);
6
        for(int i=1; i<n; i++){
7
            dp[i] = dp[i-1] + triangle.get(i).get(i); 
8
            for(int j=i-1; j>0; j--){
9
                dp[j] = Math.min(dp[j], dp[j-1])+triangle.get(i).get(j);
10
            }
11
            dp[0] = dp[0] + triangle.get(i).get(0);
12
        }
13
        int ans = dp[0];
14
        for(int i=1; i<n; i++){
15
            ans = Math.min(ans, dp[i]);
16
        }
17
        return ans;
18
    }
19
}