zoukankan      html  css  js  c++  java
  • 动态规划(4)--------仍然是一个简单的例子

    给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
    
    例如,给定三角形:
    
    [
         [2],
        [3,4],
       [6,5,7],
      [4,1,8,3]
    ]
    
    自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
    
    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/triangle
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

           经过上几次的分析,我们应该知道了,动态规划的关键是找到状态转移方程。对于此问题,我想状态转移方程是很明显的。节点[i,j],选择min([i-1,j],[i-1,j-1]),然后加上自己的数。注意,题干说的相邻指的是节点[i,j]和节点[i+1,j],[i+1,j+1]相邻。那么此处将会有两种解法,自顶向下和自底向上,显然,对于自顶向下,我们需要选择min([i-1,j],[i-1,j-1]),但是此处存在一个问题,即,上层比下层长度短,那么越界问题必然需要注意,此外还有j-1,需要单独讨论j=0的情况,

          下面先给出自顶向下的代码

    public int minimumTotal(List<List<Integer>> triangle) {
            int rows = triangle.size();
            if(rows == 0)
                return 0;
            int[][] dp = new int[rows][rows];
            dp[0][0] = triangle.get(0).get(0);
            for(int i=1;i<triangle.size();++i){
                List<Integer> array = triangle.get(i);
                for(int j=0;j<array.size();++j){
                    if(j>0 && j<array.size()-1){
                        dp[i][j] = Math.min(dp[i-1][j-1],dp[i-1][j]) + array.get(j);
                    }else {
                        if(j == 0)
                            dp[i][j] = dp[i-1][j] + array.get(j);
                        if(j == array.size()-1)
                            dp[i][j] = dp[i-1][j-1] + array.get(j);
                    }
                }
            }
            int ans = dp[rows-1][0];
            for(int i=1;i<rows;++i)
                ans = ans<=dp[rows-1][i]?ans:dp[rows-1][i];
            return ans;
    
        }

          对于自底向上的传递,由于相邻规则的限制,无需考虑数组越界的问题,其思路和上述一致。

    public int minimumTotal(List<List<Integer>> triangle) {
            int rows = triangle.size();
            if(rows == 0)
                return 0;
            int cols = triangle.get(rows-1).size();
            int[][] dp = new int[rows+1][rows+1];               
            for (int i=triangle.size()-1;i>=0;--i){
                List<Integer>array = triangle.get(i);
                for(int j=0;j<array.size();++j){
                    dp[i][j] = Math.min(dp[i+1][j],dp[i+1][j+1])+array.get(j);
                }
            }
            return dp[0][0];
        }

           可以看出来,自底向上明显比自顶向下简介的多。

           此外,上述代码的空间复杂度可以进一步降低。有兴趣可以试试

  • 相关阅读:
    JAVA,JSP,Servlet获取当前工程路径-绝对路径
    Oracle中Null与空字符串' '的区别
    使用JDBC调用存储过程
    oracle 11g SQL语句补充学习
    flutter 登录后跳转到根路由
    Mac下mongodb connect failed 连接错误解决方法
    flutter 新增安卓ios 闪图
    npm 发布包
    js中setTimeout() 时间参数为0
    ionic3 打包 混淆代码
  • 原文地址:https://www.cnblogs.com/establish/p/11802256.html
Copyright © 2011-2022 走看看