zoukankan      html  css  js  c++  java
  • [leetcode] Triangle

    Triangle

    Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.

    For example, given the following triangle

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

    The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).

    Note:
    Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.

    思路:

    上来就dfs,从根节点到叶子节点,递归找最小值。结果大数据就超时了。

    class Solution {
    public:
        int res = INT_MAX;
        void minipath(vector<vector<int> > &triangle, int row, int col, int sum) {
            if(row==triangle.size()) {
                res = min(res, sum);
                return;
            }
            sum += triangle[row][col];
            minipath(triangle, row+1, col, sum);
            minipath(triangle, row+1, col+1, sum);
        }
        int minimumTotal(vector<vector<int> > &triangle) {
            minipath(triangle, 0, 0, 0);
            return res;
        }
    };
    TLE

    超时那就肯定不能递归了,仔细想想发现这题可以用动态规划来解。从根节点到第i行第j列的最小和 sum[i][j]=triangle[i][j]+min(sum[i-1][j], sum[i-1][j-1]),这就是动态规划的式子。所以采用自顶向下法,开辟一个二位数组dp[][],其中dp[i][j]代表从根节点到第i行第j列的最小和,剩下的就是注意边界条件,就可以得到AC的解。

    class Solution {
    public:
        int minimumTotal(vector<vector<int> > &triangle) {
            int row = triangle.size();
            int col = triangle[row-1].size();
            int **dp = new int*[row];
            for(int i=0;i<row;i++)
                dp[i] = new int [col];
            dp[0][0] = triangle[0][0];
            for(int i=1;i<row;i++) {
                int len = triangle[i].size();
                for(int j=0;j<len;j++) {
                    if(j==0)
                        dp[i][0] = dp[i-1][0]+triangle[i][0];
                    else if(j==len-1)
                        dp[i][j] = dp[i-1][j-1]+triangle[i][j];
                    else
                        dp[i][j] = min(dp[i-1][j-1], dp[i-1][j])+triangle[i][j];
                }
            }
            row -= 1;
            int res = dp[row][0];
            for(int j=1;j<col;j++) 
                res = min(res, dp[row][j]);
            return res;
        }
    };
    O(n^2)

    但是上面的解法还是有一个问题,题目的要求是用O(n)的空间复杂度,我的是用的O(n^2)空间复杂度。于是我傻了,想不出哪里可以优化的地方,只好求助万能的百度。在看别人写的博客时,发现了一种自底向上法,这样就省去了前面的边界条件的判断,很厉害。感谢作者。其实从O(n^2)到O(n)的过程,需要发现根节点到本层所有列的最小和,与上一层有着直接的关系,而与本层之后的结果没有直接的关系,因此计算本层的结果时,可以覆盖上一层的结果。

    class Solution {
    public:
        int minimumTotal(vector<vector<int> > &triangle) {
            int n = triangle.size();
            int *dp = new int [n];
            for(int i=n-1;i>=0;i--)
                for(int j=0;j<=i;j++) {
                    if(i==n-1) {
                        dp[j] = triangle[i][j];
                    }
                    else {
                        dp[j] = triangle[i][j]+min(dp[j], dp[j+1]);
                    }
                }
            return dp[0];
        }
    };
    View Code

    最后,注意边界条件,用自顶向下法也可以做出来,详见此处

  • 相关阅读:
    Python 日志处理(三) 日志状态码分析、浏览器分析
    Python 日志处理(二) 使用正则表达式处理Nginx 日志
    mongodb关联查询 和spring data mongodb
    redis实现分布式锁
    springboot使用过滤器和拦截器
    springboot使用schedule定时任务
    fastjson格式化输出内容
    logback-spring.xml
    spring data jpa封装specification实现简单风格的动态查询
    spring data jpa自定义baseRepository
  • 原文地址:https://www.cnblogs.com/jiasaidongqi/p/4210535.html
Copyright © 2011-2022 走看看