• 因为它,差点无缘大厂梦!!!


    前言

    今天,小莱在leetcode上闲逛,突然眼前一亮,咦!这不是去年来百度二面时的一道算法题吗?没想到在这遇到了。想当时险些栽到上边,不过最后千钧一发之际,还是想到了解决方法,顺利拿到offer 。

    画外音:后来,在小米的面试环节中也遇到了此题。

    那么,今天小莱就给大家分享下这道动态规划题。 

    题目:

    一个机器人位于一个 m × n 网格的左上角(起始点在下图中标记为“Start” )。

    机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

    问总共有多少条不同的路径?

    说明:m 和 n 的值均不超过 100。

    例如,上图是一个7 × 3 的网格。有多少可能的路径?

    画外音:Leetcode第62题,中等/难度。

    不同路径

    我们由终点位置倒推,从图中可以看出,想要到达终点,A、B两点是必经之路。那么,我们想要得到起点到终点的路径数,计算出到达A、B两点的路径总数不就能够得出来了吗?但是A、B两点的路径数如何得出呢。

    我们不妨再往前推,到达A点需要经过C或者D这两点,到达A点的路径数可以通过到达C、D两点的路径总数得知。

    同样地,到达B点需要经过D点或E点,到达B点的路径数可以通过到达D、E两点的路径总数得知。

    到这,聪明的你有没有发现规律:

    每一个点可到达路径数 = 其相邻左边点可到达路径数 + 其相邻上边点可到达路径数

    现在,我们可以回到起点了。 

    我们可以把m×n方格看作一个二维数组,数组中的每个元素表示:

    起点到该方格的路径数

    起点到该方格的路径数

    起点到该方格的路径数

    (默念三遍!!!)

    如下图中,机器人到达第X行(仅第0行)或第Y列(仅第0列)中的任意方格都只有一条路径。因此,我们将第X行、第Y列的方格元素都置为1。 

    接着,我们继续向其它点走。现在分别经过路径一、路径二走到了S点,因此到达S点的路径有2条。

    最终,我们得到这样一张网格,每个格子里记录了起点到该格的路径数。 

    但是如何用代码表示呢?上边提到,我们可以将其看作一个二维数组v[m][n]。初始时,将第0行、第0列赋值为1。通过双层循环,将目标点的上边元素与左边元素相加,即可得到当前路径数。

    代码实现:

    int uniquePaths(int m, int n){
        if (m == 1 || n == 1) {
            return 1;
        }

        int i, j;
        int v[m][n];

        for (i = 1; i < m; i++) {
            v[i][0] = 1;
            for (j = 1; j < n; j++) {
                v[0][j] = 1;
                v[i][j] = v[i][j-1] + v[i-1][j];
            }
        }

        return v[m-1][n-1];
    }

    画外音:本文使用C语言实现,但是不会涉及复杂的语言特性,所以无需担心看不懂。另外,代码实现小莱在leetcode亲测!!!

    不同路径 II

    进行到这里,我们就实现了机器人从起点到终点畅通无阻情况下所要走的路径。 

    你可能注意到了,小莱重点标记了下『畅通无阻』这4个字,这说明还有存在障碍物的情况。那么现在我们就来看看,存在障碍物的情况下,机器人所走的路径数有多少。

    画外音:此题为Leetcode第63题,中等/难度。

    如图中,给定一个二维数组obstacleGrid[m][n],用1来表示障碍物,用0表示空位置。

    同样地,我们还是用二维数组v[m][n]来表示机器人到达某个方格的路径数。

    但是在处理时,与无障碍物不同的是,其不再是简单向右或向下移动。初始化和计算时要考虑障碍。

    这里分为两种情况: 

    1、当障碍物出现在第0行或第0列,此时一旦遇到障碍,后续方格无法到达,因此后续行列路径数只能为0;

    画外音:这里只给出第0行、第0列路径数。

    2、当障碍物出现在非第0行与第0列的任意位置时,如果当前方格为障碍物时,可以直接将该方格赋值为0;

    现在我们可以通过代码来实现了,首先初始化二维数组v[m][n],值默认都为0。接着初始化第0行和第0列,当未遇到障碍物时路径数为1,否则为0,其后方格的路径也都为0。然后通过双层循环,将目标点的上边元素与左边元素相加,即可得到当前路径数(在这个过程中如果遇到障碍物的话其方格数为0)。

    代码实现:

    int uniquePathsWithObstacles(int** obstacleGrid, int obstacleGridSize, int* obstacleGridColSize){
        // m代表行 n代表列
        int m = obstacleGridSize, n = * obstacleGridColSize;
        if (obstacleGrid[0][0] == 1) {
            return 0;
        }

        int i, j;
        int v[m][n];
        memset(v, 0, m * n * sizeof(int));
        //初始化第一列
        for (i = 0; i < m; i++) {
            if (obstacleGrid[i][0] == 1) {
                break;
            }
            v[i][0] = 1;
        }
        //初始化第一行
        for (j = 0; j < n; j++) {
            if (obstacleGrid[0][j] == 1) {
                break;
            }
            v[0][j] = 1;
        }

        for (i = 1; i < m; i++) {
            for (j = 1; j < n; j++) {
                v[i][j] = obstacleGrid[i][j] == 1 ? 0 : (v[i][j-1] + v[i-1][j]);
            }
        }

        return v[m-1][n-1];
    }

    关于作者

    作者:大家好,我是莱乌,BAT搬砖工一枚。从小公司进入大厂,一路走来收获良多,想将这些经验分享给有需要的人,因此创建了公众号「IT界农民工」。定时更新,希望能帮助到你。

     
  • 相关阅读:
    git在eclipse中的配置 转载
    Java annotation 自定义注释@interface的用法 转载记录
    Java内存溢出的详细解决方案 转载
    sql server 分页、存储过程、视图
    重新认识Asp.Net管道模型
    vim修改替换
    Excel hong
    开始第一次Delphi
    常用正则表达式的网站
    := 赋值语句
  • 原文地址:https://www.cnblogs.com/caoyier/p/13870494.html
Copyright © 2020-2023  润新知