每日打卡:最小路径和

164 阅读2分钟

这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战

给定一个包含非负整数的 _m_ x _n_ 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明: 每次只能向下或者向右移动一步。

minpath.jpg

输入:grid = [[1,3,1],[1,5,1],[4,2,1]] 输出:7 解释:因为路径 1→3→1→1→1 的总和最小。

这是一道很典型的动态规划题

BF9D0B2F98F3B90C3A42B31B1D0AF80D.jpg

我们从左上角到右下角,所以我们的移动方式就只有向左和向右,那我们把这个题简单画一下

F7FA0056BBAFDE42341EF05B03AE7D0E.jpg

我们先看这四个单位,1—5,我们只需要5这个单元格上面和左面格子的步数,进行比较后再相加。其实这就可以看作是我们的状态转移方程

//我们最开始需要我们的横竖最开始的两条边,

public int minPathSum(int[][] grid) {
        if(grid == null || grid.length==0|grid[0].length==0){
            return 0;
        }
        
      
        int row = grid.length;
        int col = grid[0].length;
        //创建一个数组用来存储我们的走到每个位置的相应步数
        int [][]dp = new int[row][col];
        dp[0][0] = grid[0][0];
        //我们最开始需要我们的横竖最开始的两条边每条的步数
        for(int i = 1; i<row; i++){
            dp[i][0] = dp[i-1][0]+grid[i][0];
        }
        for(int i=1;i<col;i++){
            dp[0][i] = dp[0][i-1] + grid[0][i];
        }
        for(int i = 1; i<row; i++){
            for(int j=1;j<col;j++){
                dp[i][j] = Math.min(dp[i-1][j],dp[i][j-1])+grid[i][j];
            }
        }
        return dp[row-1][col-1];
    }

我们整个步骤就是再给我们步数数组赋值的过程,而且我们每次赋值都是进行了选择,因为我们需要的是上面的格子和左面的格子,经过比较后再进行选择走哪一条路,其中 dp[i][j] 表示我们的目的地,dp[i-1][j] 表示我们的这个格子上面的格子,dp[i][j-1] 表示我们的这个格子左面的格子。

1EA506C82BE38171AE657A973C901F59.jpg

当我们的把每一个选择都走过之后,我们只需要把最右下角步数返回就是最少的步数。

我们目前是使用一个二维数组来存储我们的步数,观察我们的存储过程,其实我们的不需要那么多的数组,我们也可以使用一个一维数组来存我们的步数

具体的实现可以看一看

动态规划DP - 掘金 (juejin.cn)

文章中最长公共子序列(LCS)