算法初探LeetCode-不同路径 II

117 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2 天,点击查看活动详情

LeetCode63:不同路径

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

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

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

网格中的障碍物和空位置分别用 1 和 0 来表示。

示例 1:

输入: obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出: 2
解释: 3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:
1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右

示例 2:

输入: obstacleGrid = [[0,1],[0,0]]
输出: 1

提示:

  • m == obstacleGrid.length
  • n == obstacleGrid[i].length
  • 1 <= m, n <= 100
  • obstacleGrid[i][j] 为 0 或 1

思路分析

动态规划算法往往不直观,但其是对暴力算法的一种优化,比如增加记忆功能。本题典型的动态规划,根据提示可轻松实现.

根据题意本题的核心思路: 定义一个二维数组dp[i][j]dp[i][j]表示到坐标(i,j)(i,j)共有多少种走法状态转移方程:因为一个坐标的上一步来源只能是坐标的左边或者坐标的右边 所以dp[i][j]=dp[i1][j]+dp[i][j1]dp[row1][col1]dp[i][j] = dp[i - 1][j] + dp[i][j - 1] dp[row - 1][col - 1]即为返回答案!

值得注意的就是,如果最右下角的格子有障碍时,直接返回0,单独拿出来做处理!

算法代码

public static int uniquePathsWithObstacles(int[][] obstacleGrid) {
    int row = obstacleGrid.length;
    int col = obstacleGrid[0].length;
    /**
     * 如果终点有障碍 则直接返回0!
     */
    if (obstacleGrid[row - 1][col - 1] == 1) return 0;
    int[][] dp = new int[row][col];
    /**
     * 初始化 0,0坐标做法只有一种
     */
    dp[0][0] = 1;
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            /**
             * 因为0,0坐标已经初始化过了,不需要再处理
             * 第一个坐标是起始点,没有上一步,所以不需要处理
             */
            if (i == 0 && j == 0) continue;
            /**
             * 除了边界坐标外,一般坐标都会有两种来源(即上一步的格子位置)
             * (这里先不考虑障碍问题,因为再getDp方法中已经有处理了)
             * 坐标左边 or 坐标上边
             * 因为机器人只能向右走 or 向下走!!!!
             */
            dp[i][j] = getDp(dp, i - 1, j, obstacleGrid) + getDp(dp, i, j - 1, obstacleGrid);
        }
    }
    return dp[row - 1][col - 1];
}

public static int getDp(int[][] dp, int i, int j, int[][] obstacleGrid) {
    if (i < 0 || j < 0 || obstacleGrid[i][j] == 1) {
        /**
         *  i,j都小于0说明该坐标的上一步中某一来源是边界外
         *  即该坐标是边界坐标,只有一种来源,要么从坐标上面来,要么从坐标左边来
         *  obstacleGrid[i][j] == 1 说明该坐标处有障碍,则上一步不能上该坐标,所以和边界外一样的处理,直接返回0即可!
         */
        return 0;
    } else {
        return dp[i][j];
    }
}

结果详情

Snipaste_2023-02-05_23-21-42.png

算法复杂度

  • 空间复杂度:O(n)O(n)
  • 时间复杂度:O(n2)O(n^2)

掘金(JUEJIN)一起进步,一起成长!