zoukankan      html  css  js  c++  java
  • leetcode-64. 最小路径和 · vector + DP

    题面

    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.

    Note: You can only move either down or right at any point in time.

    给定二维数组,从(0, 0)开始,只能向右和向下走,找到最小的路径和。

    样例

    Input:
    [
      [1,3,1],
      [1,5,1],
      [4,2,1]
    ]
    Output: 7
    Explanation: Because the path 1→3→1→1→1 minimizes the sum.

    思路

    动态规划,打表。我们就模拟移动的路径。我们需要一个二维数组来存储每一步的路径值。

    可以在原来二维数组基础上,直接进行操作。

    第一排只能向右走得到;第一列只能向下走得到。

    其他的就要参考它的上边元素值和左边元素值,取小在加上它本身,更新成为它。(因为要最小路径,所以我们要确保每一步都最小)

    算法

    1. 遍历第一行,当前元素值为它左边元素加上它本身(只能从左边向右边走);

    2. 遍历第一列,当前元素值为它上边元素加上它本身(只能从上边向下边走);

    3. 遍历二维数组其他元素,当前值为上边元素与左边元素最小值加上它本身;

    4. 返回右下角元素,即是结果。

    时间复杂度:O(n2)

    空间复杂度:O(n2)

    源码

     1 class Solution {
     2 public:
     3     int minPathSum(vector<vector<int>>& grid) {
     4         int row = grid.size(), col = grid[0].size();
     5         if(row == 0)
     6             return 0;
     7         for(int i=1; i<col; i++)
     8         {
     9             grid[0][i] += grid[0][i-1];
    10         }
    11         for(int i=1; i<row; i++)
    12         {
    13             grid[i][0] += grid[i-1][0];
    14         }
    15         for(int i=1; i<row; i++)
    16         {
    17             for(int j=1; j<col; j++)
    18             {
    19                 grid[i][j] += min(grid[i][j-1], grid[i-1][j]);
    20             }
    21         }
    22         return grid[row-1][col-1];
    23     }
    24 };

    优化:空间压缩

    其实,我们在做的过程当中,一直在做行处理,即一直在更新某一行(更新完这一行就转向下一行)。那么,我们只需要一个一维数组即可解决这个问题。

    这样一来,空间就压缩到了O(n),时间复杂度不变。

    (1-压缩后的;2-压缩前的)似乎空间占用也没有多大变化,但是我们确实做了空间压缩。

    空间压缩源码

    只用一维数组在存储状态,就要重新推导一下更新的状态方程

    第一行:dp[0] = grid[0][0]

        dp[i] = grid[0][i] +  dp[i-1]

    其他行:dp[0] = grid[i][0] + dp[0]

        dp[j] = grid[i][j] +  min(dp[j-1], dp[j])

     1 int minPathSum(vector<vector<int>>& grid) {
     2         int row = grid.size(), col = grid[0].size();
     3         if(row == 0)
     4             return 0;
     5         vector<int> dp(col, 0);//只要额外一维数组的空间,上一种做法,如果不原地使用原来二位数组的话,就只能额外开二维数组。
     6         dp[0] = grid[0][0];
     7         for(int i=1; i<col; i++)
     8         {
     9             dp[i] = dp[i-1] + grid[0][i];
    10         }
    11         for(int i=1; i<row; i++)
    12         {
    13             dp[0] += grid[i][0];
    14             for(int j=1; j<col; j++)
    15             {
    16                 dp[j] = min(dp[j-1], dp[j]) + grid[i][j];
    17             }
    18         }
    19         return dp[col-1];
    20     }
  • 相关阅读:
    线程(C++11)
    初始化、赋值
    优质学习资料总结
    移植之乱谈
    采集音频和摄像头视频并实时H264编码及AAC编码
    H264解码器源码(Android 1.6 版)
    移植ffmpeg到VC环境心得
    收集的网络上大型的开源图像处理软件代码(提供下载链接)
    C++开源库,欢迎补充。
    一个轻量级AOP的实现(开源)
  • 原文地址:https://www.cnblogs.com/yocichen/p/10885832.html
Copyright © 2011-2022 走看看