LeetCode每日一题--120. 三角形最小路径和(Java)

153 阅读2分钟

DailyChallenge

120. 三角形最小路径和

Medium20200714

Description

给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。

相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。

例如,给定三角形:

[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

说明

如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。

链接leetcode-cn.com/problems/tr…

Solution

  1. 入门 二维dp数组
class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        int m = triangle.size();
        int n = triangle.get(m - 1).size();

        int[][] dp = new int[m + 1][n + 1];
        int INF = Integer.MAX_VALUE / 4;
        for(int i = 0; i < m; i++) Arrays.fill(dp[i], INF);
        dp[0][0] = triangle.get(0).get(0);

        for(int i = 1; i < m; i++){
            for(int  j = 0; j < triangle.get(i).size(); j++){
                // System.out.println(triangle.get(i).size());
                if(j == 0) dp[i][j] = dp[i - 1][j] + triangle.get(i).get(j);
                else    dp[i][j] = Math.min(dp[i - 1][j], dp[i - 1][j - 1]) + triangle.get(i).get(j); 
                // System.out.println(i+"\t"+j+"\t"+dp[i][j]);
            }
        }
        int res = Integer.MAX_VALUE/4;
        for(int j = 0; j < n; j++) res = Math.min(res, dp[m - 1][j]);
        return res;
    }
}
  1. 进阶,用一维dp数组

和0-1背包类似,如果改成一维dp数组,为了防止重复计算,就要从大到小遍历。

解释一下为什么从小到大遍历会有重复计算:

dp[i][j] = Math.min(dp[i - 1][j], dp[i - 1][j - 1])改成dp[j] = Math.min(dp[j], dp[j - 1]),如果j从小到大遍历,那么这个时刻的dp[j - 1]就是已经被上一次循环更新过的,因此二维表示应该是dp[i][j - 1]。这样不符合转移方程;如果j从大到小遍历,那么这个时刻的dp[j - 1]还未被更新过,因为它的二维表示是dp[i - 1][j - 1],这样才符合转移方程。

class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        int m = triangle.size();
        int n = triangle.get(m - 1).size();
        int[] dp = new int[n];
        int INF = Integer.MAX_VALUE / 4;
        Arrays.fill(dp, INF);
        dp[0] = triangle.get(0).get(0);

        for(int i = 1; i < m; i++){
            for(int  j = triangle.get(i).size() - 1; j >= 0 ; j--){
                if(j == 0) dp[j] = dp[j] + triangle.get(i).get(j);
                else    dp[j] = Math.min(dp[j], dp[j - 1]) + triangle.get(i).get(j); 
            }
        }
        int res = INF;
        for(int d : dp) res = Math.min(res, d);
        return res;
    }
}


我的公众号:GitKid

暂时每日分享LeetCode,我在不断学习的过程中,公众号也在不断充实,欢迎大家扫码关注。

TODO:动态规划专题

微信公众号
微信公众号

本文使用 mdnice 排版