算法leetcode|63. 不同路径 II(rust重拳出击)


文章目录


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:

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:

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++:

cpp 复制代码
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:

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:

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/ 博客原创~


相关推荐
DokiDoki之父2 分钟前
Spring—注解开发
java·后端·spring
Theodore_10223 分钟前
机器学习(6)特征工程与多项式回归
深度学习·算法·机器学习·数据分析·多项式回归
知花实央l3 分钟前
【算法与数据结构】拓扑排序实战(栈+邻接表+环判断,附可运行代码)
数据结构·算法
lingling00910 分钟前
机械臂动作捕捉系统选型指南:从需求到方案,NOKOV 度量光学动捕成优选
人工智能·算法
不爱洗脚的小滕17 分钟前
【Redis】三种缓存问题(穿透、击穿、双删)的 Golang 实践
redis·缓存·golang
吃着火锅x唱着歌20 分钟前
LeetCode 410.分割数组的最大值
数据结构·算法·leetcode
提笔了无痕21 分钟前
什么是Redis的缓存问题,以及如何解决
数据库·redis·后端·缓存·mybatis
浪里行舟27 分钟前
国产OCR双雄对决?PaddleOCR-VL与DeepSeek-OCR全面解析
前端·后端
lang2015092841 分钟前
Spring Boot缓存机制全解析
spring boot·后端·缓存
Benny_Tang43 分钟前
题解:P7989 [USACO21DEC] Bracelet Crossings G
c++·算法