• 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.

    这道题和Dungeon Game 地牢游戏非常的类似,都是用动态规划Dynamic Programming来求解的问题。而且递推式也比较容易看出来,我最先想到的方法是:

    从第二行开始,triangle[i][j] = min(triangle[i - 1][j - 1], triangle[i - 1][j]), 然后两边的数字直接赋值上一行的边界值,由于限制了空间复杂度,所以我干脆直接就更新triangle数组,代码如下:

     1 class Solution {
     2 public:
     3     int minimumTotal(vector<vector<int> > &triangle) {
     4         int n = triangle.size();
     5         for (int i = 1; i < n; ++i) {
     6             for (int j = 0; j < triangle[i].size(); ++j) {
     7                 if (j == 0) triangle[i][j] += triangle[i - 1][j];
     8                 else if (j == triangle[i].size() - 1) triangle[i][j] += triangle[i - 1][j - 1];
     9                 else {
    10                     triangle[i][j] += min(triangle[i - 1][j - 1], triangle[i - 1][j]);
    11                 }
    12             }
    13         }
    14         int res = triangle[n - 1][0];
    15         for (int i = 0; i < triangle[n - 1].size(); ++i) {
    16             res = min(res, triangle[n - 1][i]);
    17         }
    18         return res;
    19     }
    20 };

    这种方法可以通过OJ,但是毕竟修改了原始数组triangle,并不是很理想的方法。在网上搜到一种更好的DP方法,这种方法复制了三角形最后一行,作为用来更新的一位数组。然后逐个遍历这个DP数组,对于每个数字,和它之后的元素比较选择较小的再加上上面一行相邻位置的元素做为新的元素,然后一层一层的向上扫描,整个过程和冒泡排序的原理差不多,最后最小的元素都冒到前面,第一个元素即为所求。代码如下:

     1 class Solution {
     2 public:
     3     int minimumTotal(vector<vector<int> > &triangle) {
     4         int n=triangle.size();
     5         vector<int> dp(triangle.back());
     6         for(int i=n-2;i>=0;i--){
     7             for(int j=0;j<triangle[i].size();j++){
     8                 dp[j]=min(dp[j],dp[j+1])+triangle[i][j];
     9             }
    10         }
    11         return dp[0];
    12     }
    13 };

    下面我们来看一个例子,对于输入数组:

         -1

        2   3

      1  -1  -3

    5   3   -1   2

    下面我们来看DP数组的变换过程。

    DP:5  3  -1  2

    DP:4  3  -1  2  :1+min(5,3)=4

    DP:4  -2  -1  2 :-1+min(3,-1)=-2

    DP:4  -2  -4  2 :-3+min(-1,2)=-4

    DP:0  -2  -4  2 :2+min(4,-2)=0

    DP:0  -1  -4  2 :3+min(-2,-4)=-1

    DP:-2  -1  -4  2 :-1+min(0,-1)=-2

  • 相关阅读:
    src和href属性的区别
    cookie, sessionStorage和localStorage的区别
    C# base64 转 byte[]
    C# 中字符串string和字节数组byte[]的转换
    C#获取当前路径的七种方法 【转载】
    C# 读取大文件 (可以读取3GB大小的txt文件)
    伪装文件到图片工具
    nmap命令扫描存活主机
    .deb文件如何安装,Ubuntu下deb安装方法图文详解
    kali修改更新源及更新
  • 原文地址:https://www.cnblogs.com/zl1991/p/7001800.html
Copyright © 2020-2023  润新知