lc_dp_120_minimumTotal

18 篇文章 0 订阅

题目:三角形最小路径和 middle

给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
相邻的结点 在这里指的是下标与上一层结点下标相同或者等于上一层结点下标 + 1 的两个结点。

例如,给定三角形:

[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]

自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

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

 

package leetCode.DP;

import java.util.List;

public class lc_dp_120_minimumTotal {


    /*
    思路:
    关键字:最小路径和-->dp

    错误:
    1.状态
    1)最后一步
    sum(n)=sum(n-1)+an
    2)子问题
    自顶向到n-1层的最小路径和
    !!!这里出现问题!!!答案可能是到n-1层的路径和不一定会最小,但到(i,j)位置时和为最小
    dp[i]表示自顶到i层的最小路径和
    2.转移方程
    dp[i]=dp[i-1]+min{ai,ai+1}
    3.初始条件和边界条件
    dp[0]=a0;
    i-1>=0;

    正确:
    该三角形就是矩形的变种,要看成二维的
    1.状态
    1)最后一步
        从a[i-1][j]到 a[i][j];sum[i-1][j]+a[i][j]
      或从a[i-1][j-1]到 a[i][j];sum[i-1][j-1]+a[i][j]
    2)子问题
       求到(i-1,j)位置的最小路径和以及到(i-1,j-1)位置的最小路径和
     所以dp应该是个二维数组,且dp[i][j]表示到(i,j)的最小路径和
    2.转移方程
     dp[i][j]=min{dp[i-1][j]+dp[i-1][j-1]}+a[i][j];
    3.初始条件和边界条件
     dp[0][0]=a[0][0];
     i-1>=0;j-1>=0;
优化: 因为递推式只和前一行有关,dp可以优化成一维数组,初始版本为minimumTotal2

    */
    
    //    因为递推式只和前一行有关,dp可以优化成一维数组
    public int minimumTotal(List<List<Integer>> triangle) {

        int[] dp = new int[triangle.size()];
        dp[0] = triangle.get(0).get(0);
        int min = Integer.MAX_VALUE;
        for (int i = 1; i < triangle.size(); i++) {
            List<Integer> row = triangle.get(i);
//          每一行从后往前计算,如果从前往后,后面所需的dp[j-1]将不再是上一行的值,
//          会被替换成本行前一个的值,
            for (int j = i; j >= 0; j--) {
                //处理第一列的情况,第一列只能从dp[i - 1][j]到达
                if (j == 0)
                    dp[j] = dp[j] + row.get(j);
                    //处理每行最后一个的情况,最后一个只能从dp[i - 1][j - 1]到达
                else if (j == i)
                    dp[j] = dp[j - 1] + row.get(j);
                else
                    dp[j] = Math.min(dp[j], dp[j - 1]) + row.get(j);

            }
        }
        //遍历最后一行,找最小值
        for (int i = 0; i < dp.length; i++) {
            min = Math.min(min, dp[i]);
        }

        return min;
    }


//    未优化版本
    public int minimumTotal2(List<List<Integer>> triangle) {

        int[][] dp = new int[triangle.size()][triangle.size()];
        dp[0][0] = triangle.get(0).get(0);
        int min = Integer.MAX_VALUE;
        for (int i = 1; i < triangle.size(); i++) {
            List<Integer> row = triangle.get(i);
            for (int j = 0; j < row.size(); j++) {
                //处理第一列的情况,第一列只能从dp[i - 1][j]到达
                if (j == 0)
                    dp[i][j] = dp[i - 1][j] + row.get(j);
                    //处理每行最后一个的情况,最后一个只能从dp[i - 1][j - 1]到达
                else if (j == i)
                    dp[i][j] = dp[i - 1][j - 1] + row.get(j);
                else
                    dp[i][j] = Math.min(dp[i - 1][j], dp[i - 1][j - 1]) + row.get(j);

            }
        }
        //遍历最后一行,找最小值
        int[] lastRow = dp[triangle.size() - 1];
        for (int i = 0; i < lastRow.length; i++) {
            min = Math.min(min, lastRow[i]);
        }

        return min;
    }


}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值