淘先锋技术网

首页 1 2 3 4 5 6 7


63. 不同路径 II:

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

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

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

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

样例 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

分析:

  • 面对这道算法题目,二当家的再次陷入了沉思。
  • 这道题和62. 不同路径 类似,但是由于有随机位置的障碍物,所以就不能直接用数学的组合数方式求解了。
  • 那么动态规划成了此时的优选。每一个点的不同路径数是到达上面点的不同路径数与到达左面不同路径数的和。我们可以按行从上到下的方式处理(按列从左到右处理也是可以的,但是有些别扭,因为二维数组的第一维是行,第二维是列,习惯上都是按行处理),这样会发现每行只和上一行的结果有关系,所以就不需要 m * n 的额外空间,而只需要 m 的空间,即滚动数组的思想。

题解:

rust:

impl Solution {
    pub fn unique_paths_with_obstacles(obstacle_grid: Vec<Vec<i32>>) -> i32 {
        let rows = obstacle_grid.len();
        let cols = obstacle_grid[0].len();
        let mut dp = vec![0; cols];

        if obstacle_grid[0][0] == 0 {
            dp[0] = 1;
        }

        (0..rows).for_each(|r| {
            (0..cols).for_each(|c| {
                if obstacle_grid[r][c] == 1 {
                    dp[c] = 0;
                } else if c > 0 && obstacle_grid[r][c - 1] == 0 {
                    dp[c] += dp[c - 1];
                }
            });
        });

        return dp[cols - 1];
    }
}

go:

func uniquePathsWithObstacles(obstacleGrid [][]int) int {
    rows, cols := len(obstacleGrid), len(obstacleGrid[0])
	dp := make([]int, cols)

	if obstacleGrid[0][0] == 0 {
		dp[0] = 1
	}

	for r := 0; r < rows; r++ {
		for c := 0; c < cols; c++ {
			if obstacleGrid[r][c] == 1 {
				dp[c] = 0
				continue
			}
			if c > 0 && obstacleGrid[r][c-1] == 0 {
				dp[c] += dp[c-1]
			}
		}
	}

	return dp[cols-1]
}

c++:

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        const int rows = obstacleGrid.size(), cols = obstacleGrid.at(0).size();
        vector<int> dp(cols);

        dp[0] = (obstacleGrid[0][0] == 0);
        for (int r = 0; r < rows; ++r) {
            for (int c = 0; c < cols; ++c) {
                if (obstacleGrid[r][c] == 1) {
                    dp[c] = 0;
                    continue;
                }
                if (c > 0 && obstacleGrid[r][c - 1] == 0) {
                    dp[c] += dp[c - 1];
                }
            }
        }

        return dp.back();
    }
};

python:

class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        rows, cols = len(obstacleGrid), len(obstacleGrid[0])
        dp = [0] * cols
        if obstacleGrid[0][0] == 0:
            dp[0] = 1
        for r in range(rows):
            for c in range(cols):
                if obstacleGrid[r][c] == 1:
                    dp[c] = 0
                    continue
                if c > 0 and obstacleGrid[r][c - 1] == 0:
                    dp[c] += dp[c - 1]
        return dp[cols - 1]


java:

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        final int   rows = obstacleGrid.length, cols = obstacleGrid[0].length;
        final int[] dp   = new int[cols];

        if (obstacleGrid[0][0] == 0) {
            dp[0] = 1;
        }

        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                if (obstacleGrid[i][j] == 1) {
                    dp[j] = 0;
                    continue;
                }
                if (j > 0 && obstacleGrid[i][j - 1] == 0) {
                    dp[j] += dp[j - 1];
                }
            }
        }

        return dp[cols - 1];
    }
}

非常感谢你阅读本文~
欢迎【点赞】【收藏】【评论】三连走一波~
放弃不难,但坚持一定很酷~
希望我们大家都能每天进步一点点~
本文由
二当家的白帽子:https://le-yi.blog.csdn.net/ 博客原创~