题目
机器人在 大小的地图的左上角(起点),每次可以 向下 或 向右 移动。要到达地图的右下角(终点)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径 ?
网格中的障碍物和空位置分别用 和
来表示。
示例 1:
输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]] 输出:2 解释:3x3 网格的正中间有一个障碍物。 从左上角到右下角一共有 2 条不同的路径:
- 向右 -> 向右 -> 向下 -> 向下
- 向下 -> 向下 -> 向右 -> 向右
解题思路:动态规划
👉 定义: 来表示从坐标
到坐标
的路径总数 。
表示坐标
是否可行,如果坐标
有障碍物,
,否则
。
「机器人每次只能向下或者向右移动一步」,所以从坐标 到坐标
的路径总数的值只取决于
与
的和。当坐标
本身有障碍的时候,任何路径都到到不了
。
状态转移方程:
边界情况:
起点和终点有障碍物,直接返回- 边界
行,
列,正常全部为
,只有一种路径可达,一直
向左或向下 - 当
出现障碍物后,
列下面的全部不可达
- 当
出现障碍物后,
行后面的全部不可达
复杂度分析
时间复杂度:,其中
为网格的行数,
为网格的列数 。
空间复杂度:,利用滚动数组优化,我们可以只用
大小来记录当前的
。
我的代码
class Solution {public static int uniquePathsWithObstacles(int[][] obstacleGrid) {// 数组空if (obstacleGrid == null || obstacleGrid.length == 0) return 0;// 起点终点有障碍物if (obstacleGrid[0][0] == 1 ||obstacleGrid[obstacleGrid.length - 1][obstacleGrid[0].length - 1] == 1) return 0;int[][] dp = new int[obstacleGrid.length][obstacleGrid[0].length];for (int i = 0; i < obstacleGrid.length; i++) {for (int j = 0; j < obstacleGrid[i].length; j++) {// 起点if (i == 0 && j == 0) {dp[0][0] = 1;continue;}// 0行if (i == 0) {// 有障碍物置零,无障碍物状态从左面转移if (obstacleGrid[0][j] == 1) dp[0][j] = 0;elsedp[0][j] = dp[0][j - 1];continue;}// 0列if (j == 0) {// 有障碍物置零,无障碍物状态从上面转移if (obstacleGrid[i][0] == 1) dp[i][0] = 0;elsedp[i][0] = dp[i - 1][0];continue;}// 非0行0列if (obstacleGrid[i][j] == 1) {dp[i][j] = 0;} else {// 无障碍物状态从上面、左面转移dp[i][j] = dp[i - 1][j] + dp[i][j - 1];}}}return dp[obstacleGrid.length - 1][obstacleGrid[0].length - 1];}}
解题思路:深搜
备注:对于题目有时间限制的可能过不了,会显示超时
从起点开始按照 右下 两个方向深搜,遇到 终点 ,结果路径增,搜索整个地图的所有路径可能性,找出最终答案数 。
我的代码
class Solution {int res = 0;// 可行用0表示,障碍物用1表示,临时访问置1public int uniquePathsWithObstacles(int[][] obstacleGrid) {// 非法判断if (obstacleGrid == null || obstacleGrid.length == 0 || obstacleGrid[0][0] == 1 ||obstacleGrid[obstacleGrid.length - 1][obstacleGrid[0].length - 1] == 1)return 0;dfs(0, 0, obstacleGrid);return res;}private void dfs(int i, int j, int[][] obstacleGrid) {// 判断边界合法性if (i < 0 || i >= obstacleGrid.length || j < 0 || j >= obstacleGrid[i].length) return;// 判断当前位置是否可行if (obstacleGrid[i][j] == 1) return;// 判断是否到达终点if (i == obstacleGrid.length - 1 && j == obstacleGrid[0].length - 1) {res++;return;}// 标记当前位置被访问obstacleGrid[i][j]=1;// 右下int[][] dir = new int[][]{{0, 1}, {1, 0}};for (int k = 0; k < dir.length; k++) {dfs(i + dir[k][0], j + dir[k][1], obstacleGrid);}// 释放当前位置的访问obstacleGrid[i][j]=0;}}
