当前位置: 首页 > article >正文

【算法题】63. 不同路径 II-力扣(LeetCode)-”如果起点有障碍物,那么便到不了终点“

【算法题】63. 不同路径 II-力扣(LeetCode)-”如果起点有障碍物,那么便到不了终点“

1.题目

下方是力扣官方题目的地址

63. 不同路径 II

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

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

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

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

示例 1:

img

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

示例 2:

img

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

提示:

  • m == obstacleGrid.length
  • n == obstacleGrid[i].length
  • 1 <= m, n <= 100
  • obstacleGrid[i][j]01

2.题解

这题有两种思路:

思路一:深度优先搜索

思路二:动态规划

思路一

路径问题我们很容易想到的是深度优先来搜索出路径,进而求出结果。

我们将路径想象成树结构,本题要求只能向下或者向右,那么这棵树就是一颗二叉树,如图所示:

在这里插入图片描述

在结合这颗树进行深度优先搜索的时候注意一下边界条件以及路径中的障碍物,这个问题就很容易解决出来了

Python代码

class Solution(object):
    def uniquePathsWithObstacles(self, obstacleGrid):
        """
        :type obstacleGrid: List[List[int]]
        :rtype: int
        """
        if obstacleGrid[0][0]==1:return 0 # 如果起点有障碍物,那么便到不了终点
        m=len(obstacleGrid)
        n=len(obstacleGrid[0])
        counts=0
        global counts
        def dfs(x,y):
            global counts
            if x==m-1 and y==n-1:
                counts+=1
                return
            for dx,dy in [[1,0],[0,1]]:
                if 0<=x+dx<m and 0<=y+dy<n:  # 确保不会越界
                    if obstacleGrid[x+dx][y+dy]!=1:dfs(x+dx,y+dy) # 以及不碰到障碍物
        dfs(0,0)
        return counts

不过显然这种方法比较低效,提交时显示的也是显示超时了

在这里插入图片描述

思路二

我们用dp[i,j]来表示从坐标 (0,0) 到坐标 (i,j) 的路径总数

那么dp[i,j]是怎么来的呢?

题目中要求只能向下或者向右走,那么反过来,坐标(i,j)只能由它的上方以及左方走过来,所以

dp[i,j]是dp[i-1,j]和dp[i,j-1]的路径总数的和

这里有一个细节需要注意:

dp元素的初始化值需要是0

这样即使(i,j)的左边或者上边有障碍物,也不影响得出的结果

所以我们可得出状态转移方程:

dp[i][j]=dp[i-1][j]+dp[i][j-1]

当然这题也有以下特殊的边界位置:第一行和第一列

其中起点位置最为特殊且如果起点有障碍物,那么无论无何也到不了终点:

if not obstacleGrid[0][0]:dp[0][0]=1
else:return 0

至于其它第一行的数,它们只能从左边走过来

以及其他第一列的数,它们只能从上边走过来

所以我们可以将它们先走完:

for i in range(1,n):
    if not obstacleGrid[0][i]:dp[0][i]=dp[0][i-1]
for j in range(1,m):
    if not obstacleGrid[j][0]:dp[j][0]=dp[j-1][0]

然后我们接着对剩下的位置进行模拟,利用状态转移方程,即可解决该问题

python代码

class Solution(object):
    def uniquePathsWithObstacles(self, obstacleGrid):
        """
        :type obstacleGrid: List[List[int]]
        :rtype: int
        """
        m=len(obstacleGrid)
        n=len(obstacleGrid[0])
        dp=[[0]*n for _ in range(m)]    # 初始化dp数组
        if not obstacleGrid[0][0]:dp[0][0]=1
        else:return 0  # 如果起点有障碍物,那么便到不了终点 
        for i in range(1,n):
            if not obstacleGrid[0][i]:dp[0][i]=dp[0][i-1]       # 将特殊值模拟完
        for j in range(1,m):
            if not obstacleGrid[j][0]:dp[j][0]=dp[j-1][0]
        for i in range(1,m):
            for j in range(1,n):                        # 模拟其他正常位置
                if not obstacleGrid[i][j]:
                    dp[i][j]=dp[i-1][j]+dp[i][j-1]      # 如果这个位置不是障碍物,则利用状态转移方程
        return dp[-1][-1]

3.结语

该题中,有一个细节:如果起点有障碍物的话,那么路径总数为0

就是本人在注释中所说的:“如果起点有障碍物,那么便到不了终点 ”。

如果不考虑这句话的绝对性,我们在学习算法的过程中何尝不是如此,万事开头难。

我相信,如果我们将学习算法的头给开好,在刚开始而又想放弃的时候再坚持一下,那么我们会在学习算法的道路上越走越远,越走越精通!希望大家在学习算法的过程中不断收获、不断成长!

本人资历尚浅,发博客主要是记录与学习,欢迎大佬们批评指教!大家也可以在评论区多多交流,相互学习,共同成长。


http://www.kler.cn/a/319522.html

相关文章:

  • C语言 | Leetcode C语言题解之第556题下一个更大元素III
  • Axure设计之文本编辑器制作教程
  • Linux如何更优质调节系统性能
  • AI制作ppt
  • 详解基于C#开发Windows API的SendMessage方法的鼠标键盘消息发送
  • 大语言模型:解锁自然语言处理的无限可能
  • 行业人工智能研究-Python自监督方式学习图像表示算法
  • mysql表逆向实体类
  • Linux 基础IO 2
  • 网络原理之IP协议(网络层)
  • java线程Thread的组名是main就是在主线程吗?
  • LeetCode 每周算法 6(图论、回溯)
  • react:React Hook函数
  • MySQL篇(存储引擎)(持续更新迭代)
  • 杂牌鼠标侧键设置
  • C++:AB5 点击消除
  • 基于大数据的电子产品需求数据分析系统的设计与实现(Python Vue Flask Mysql)
  • 每日一题|2306. 公司命名|哈希映射、集合运算
  • FastAPI挂载静态资源
  • 单词记忆的化境:用思想的流水去淹没坚硬的石块
  • 【网络安全】网络基础第一阶段——第四节:网络协议基础---- VRRP与网络架构设计
  • 三种springboot启动时加载方式
  • 使用Renesas R7FA8D1BH (Cortex®-M85)和微信小程序App数据传输
  • 黑盒测试 | 挖掘.NET程序中的反序列化漏洞
  • 统信服务器操作系统【d版系统上Ansible工具】配置方法
  • MySQL:表的约束