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

刷题记录 动态规划-5: 62. 不同路径

题目:62. 不同路径

难度:中等

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

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

问总共有多少条不同的路径?

示例 1:

输入:m = 3, n = 7
输出:28

示例 2:

输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右
3. 向下 -> 向右 -> 向下

示例 3:

输入:m = 7, n = 3
输出:28

示例 4:

输入:m = 3, n = 3
输出:6

提示:

  • 1 <= m, n <= 100
  • 题目数据保证答案小于等于 2 * 109

一、模式识别

本题我一共找到了三种解法:

首先最容易想到的就是基于递归的DFS(深度优先搜索),

然后如果沿着递推公式能想到从终点返回起点这一层就能写出动态规划解法

最后代码随想录还给出了算组合数的方法(数论),我数学没那么好,想不到

1.DFS

该方法顺着题干很容易想到,而且该方法就是动态规划方法的递推公式

2.动态规划

本题属于经典动态规划问题,而且动规的很多要素题干中已经直接给出

五部曲:

1.动规数组意义:位于位置(i, j)时剩余的总步数

2.递推公式:dp(i, j) = dp(i - 1, j) + dp(i, j - 1)

解释:

机器人处于位置(i, j)时,每次只能向下或者向右移动一步两种选择,

分别可以到达(i - 1, j)和位置(i, j - 1),

3.初始化:题干:一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )

4.遍历顺序:本题常规,根据递推公式:

行遍历套列遍历或列遍历套行遍历均可,但注意是从终点反向到起点

5.举例:当机器人走到边缘位置(m == 1 or n == 1),路径便只剩下一条

3.数论:算组合数

无论怎么走,从起点(m, n)到终点(1, 1)都要走m + n - 2步,

其中,横向m - 1步,纵向n - 1步

因此该问题就顺理成章的转化成了C(m + n - 2), (m - 1)的组合问题

二、代码实现

1.DFS

这方法很好想,而且代码简介可读性强,但就是有个小小的问题:会超时!

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        if m == 1 or n == 1:
            return 1
        return self.uniquePaths(m - 1, n) + self.uniquePaths(m, n - 1)

问题源于其指数级的时间复杂度:O(2^(m + n - 1) - 1)

2.动态规划

(1)二维OMN空间写法

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        if m == 1 or n == 1:
            return 1
        dp = [[1] * n for _ in range(m)]
        for i in range(m):
            for j in range(n):
                if i != 0 and j != 0:
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
        return dp[m - 1][n - 1]
  • 时间复杂度:O(m × n)
  • 空间复杂度:O(m × n)

耗时:0ms

(2)一维ON空间写法

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        if m == 1 or n == 1:
            return 1
        dp = [1] * n
        for i in range(m):
            for j in range(n):
                if i != 0 and j != 0:
                    dp[j] += dp[j - 1]
        return dp[n - 1]
  • 时间复杂度:O(m × n)
  • 空间复杂度:O(n)

耗时:3ms

可读性有点差,所以稍微解释一下,和二维空间代码的对应关系:

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

dp[i][j]: 更新后的dp[j]

dp[i - 1][j]: 更新前的dp[j]

dp[i][j - 1]: dp[j - 1]

3.数论:算组合数

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        num = 1
        a, b = m + n - 2, min(m - 1, n - 1)
        count = b
        while count > 0:
            num *= a
            a -= 1
            while b > 0 and num % b == 0:
                num //= b
                b -= 1
            count -= 1
        return num
  • 时间复杂度:O(m)
  • 空间复杂度:O(1)

耗时:0ms


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

相关文章:

  • MongoDb user自定义 role 添加 action(collStats, EstimateDocumentCount)
  • Linux——文件系统
  • RDP协议详解
  • 在K8S中,pending状态一般由什么原因导致的?
  • 2181、合并零之间的节点
  • 图像噪声处理技术:让图像更清晰的艺术
  • python的pre-commit库的使用
  • leetcode——从前序与中序遍历序列构造二叉树(java)
  • stm32小白成长为高手的学习步骤和方法
  • NOTEPAD++编写abap
  • 国土安全保障利器,高速巡飞无人机技术详解
  • CMD模块
  • 嵌入式八股文面试题(一)C语言部分
  • 如何处理 Typecho Joe 主题被抄袭或盗版的问题
  • SpringBoot源码解析(九):Bean定义接口体系
  • 【挖矿——前缀和】
  • 网络工程师 (15)产权人确定
  • ip归属地是不是要打开定位?
  • 【SLAM】于ubuntu18.04上纯CPU运行GCNv2_SLAM的记录(ARM64/AMD64)
  • 图 、图的存储
  • 实现数组的扁平化
  • deepseek-r1模型本地win10部署
  • 使用 SpringBoot+Thymeleaf 模板引擎进行 Web 开发
  • SRS代码目录
  • 中间件的概念及基本使用
  • 基于springboot+vue的航空散货调度系统