多路径网格问题的解决策略:比较五种不同算法【python力扣62题】

本文主要是介绍多路径网格问题的解决策略:比较五种不同算法【python力扣62题】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述

一个机器人位于一个 m x n 网格的左上角(起始点在下图标记为 “Start” )。机器人每次只能向下或向右移动一步。机器人试图达到网格的右下角(在下图标记为 “Finish”)。问总共有多少条不同的路径?

输入格式
  • m:网格的行数。
  • n:网格的列数。
输出格式
  • 返回一个整数,表示所有可能的路径数量。

示例

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

方法一:动态规划

解题步骤
  1. 初始化状态:创建一个二维数组 dp,其中 dp[i][j] 表示到达点 (i, j) 的路径数量。
  2. 边界条件:网格的第一行和第一列的路径数都是 1,因为只有一种方式到达(要么一直向右,要么一直向下)。
  3. 状态转移:对于其他位置,路径数 dp[i][j] 等于从左边来的路径数加上从上面来的路径数,即 dp[i][j] = dp[i-1][j] + dp[i][j-1]
  4. 返回结果dp[m-1][n-1] 即为所求结果。
完整的规范代码
def uniquePaths(m, n):"""使用动态规划解决不同路径问题:param m: int, 网格的行数:param n: int, 网格的列数:return: int, 不同的路径数量"""dp = [[1] * n for _ in range(m)]for i in range(1, m):for j in range(1, n):dp[i][j] = dp[i-1][j] + dp[i][j-1]return dp[m-1][n-1]# 示例调用
print(uniquePaths(3, 7))  # 输出: 28
print(uniquePaths(3, 2))  # 输出: 3
算法分析
  • 时间复杂度:(O(m * n)),需要填充一个 mn 列的矩阵。
  • 空间复杂度:(O(m * n)),使用了一个同样大小的二维数组作为动态规划表。

方法二:空间优化的动态规划

解题步骤
  1. 使用一维数组:利用一维数组 dp 来保存上一行的结果,降低空间复杂度。
  2. 迭代更新:对每一行使用相同的数组进行迭代更新,dp[j] 代表当前行第 j 列的路径数,更新公式仍为 dp[j] = dp[j] + dp[j-1]
  3. 初始化dp 的所有元素初始化为 1。
完整的规范代码
def uniquePaths(m, n):"""使用一维数组进行动态规划:param m: int, 网格的行数:param n: int, 网格的列数:return: int, 不同的路径数量"""dp = [1] * nfor i in range(1, m):for j in range(1, n):dp[j] += dp[j - 1]return dp[-1]# 示例调用
print(uniquePaths(3, 7))  # 输出: 28
print(uniquePaths(3, 2))  # 输出: 3
算法分析
  • 时间复杂度:(O(m * n)),需要迭代更新数组 m-1 次,每次迭代有 n-1 步。
  • 空间复杂度:(O(n)),使用了一个长度为 n 的一维数组。

方法三:数学组合方法

解题步骤
  1. 计算组合数:从起点到终点需要走 m+n-2 步,其中 m-1 步向下,n-1 步向右,问题转化为计算从 m+n-2 步中选择 m-1 步的组合数。
  2. 使用公式计算:使用组合数公式 C(k, n) = n! / (k! * (n-k)!) 来计算结果。
完整的规范代码
def uniquePaths(m, n):"""使用数学组合的方法解决不同路径问题:param m: int, 网格的行数:param n: int, 网格的列数:return: int, 不同的路径数量"""from math import factorialreturn factorial(m + n - 2) // (factorial(m - 1) * factorial(n - 1))# 示例调用
print(uniquePaths(3, 7))  # 输出: 28
print(uniquePaths(3, 2))  # 输出: 3
算法分析
  • 时间复杂度:(O(m + n)),计算阶乘的时间复杂度。
  • 空间复杂度:(O(1)),除输入外不需要额外的存储空间。

方法四:深度优先搜索(DFS)

解题步骤
  1. DFS递归:从起点开始,递归地探索所有向右和向下的路径。
  2. 终止条件:当到达终点时,路径计数增加。
  3. 优化:使用记忆化存储已经计算过的位置的路径数,避免重复计算。
完整的规范代码
def uniquePaths(m, n):"""使用DFS和记忆化搜索解决不同路径问题:param m: int, 网格的行数:param n: int, 网格的列数:return: int, 不同的路径数量"""memo = {}def dfs(x, y):if (x, y) in memo:return memo[(x, y)]if x == m - 1 and y == n - 1:return 1paths = 0if x < m - 1:paths += dfs(x + 1, y)if y < n - 1:paths += dfs(x, y + 1)memo[(x, y)] = pathsreturn pathsreturn dfs(0, 0)# 示例调用
print(uniquePaths(3, 7))  # 输出: 28
print(uniquePaths(3, 2))  # 输出: 3
算法分析
  • 时间复杂度:(O(m * n)),使用记忆化后避免了重复计算。
  • 空间复杂度:(O(m * n)),使用了额外的哈希表来存储中间结果。

方法五:广度优先搜索(BFS)

解题步骤
  1. 队列实现BFS:使用队列存储每个位置和到达该位置的路径数量。
  2. 逐层扩展:从起点开始,逐层扩展到可达的右侧和下侧格子。
  3. 累加路径数:到达终点的路径数累加。
完整的规范代码
from collections import dequedef uniquePaths(m, n):"""使用BFS解决不同路径问题:param m: int, 网格的行数:param n: int, 网格的列数:return: int, 不同的路径数量"""queue = deque([(0, 0)])paths = [[0] * n for _ in range(m)]paths[0][0] = 1while queue:x, y = queue.popleft()for dx, dy in [(1, 0), (0, 1)]:nx, ny = x + dx, y + dyif 0 <= nx < m and 0 <= ny < n:if paths[nx][ny] == 0:queue.append((nx, ny))paths[nx][ny] += paths[x][y]return paths[m-1][n-1]# 示例调用
print(uniquePaths(3, 7))  # 输出: 28
print(uniquePaths(3, 2))  # 输出: 3
算法分析
  • 时间复杂度:(O(m * n)),每个节点入队出队一次。
  • 空间复杂度:(O(m * n)),存储每个位置的路径数及队列的空间需求。

不同算法的优劣势对比

特征方法一: 动态规划方法二: 空间优化DP方法三: 数学组合方法四: DFS方法五: BFS
时间复杂度(O(m * n))(O(m * n))(O(m + n))(O(m * n))(O(m * n))
空间复杂度(O(m * n))(O(n))(O(1))(O(m * n))(O(m * n))
优势直观,易理解空间效率高计算最快,非迭代灵活,适用于复杂边界层次清晰,适用于大规模
劣势空间占用高优化限于列对大数处理有限制时间空间成本高需要额外存储空间

应用示例

游戏开发中的路径发现
在策略游戏或迷宫游戏中,开发者可以利用这些算法来计算从起点到终点的所有可能路径,为游戏的AI决策提供支持,比如在自动生成的迷宫中计算最优路径或在战略游戏中规划单位的行动路线。这些算法提供了不同的效率和实现复杂度,使得开发者可以根据具体游戏场景和性能要求选择最适合的方法。

这篇关于多路径网格问题的解决策略:比较五种不同算法【python力扣62题】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/931256

相关文章

Java数组初始化的五种方式

《Java数组初始化的五种方式》数组是Java中最基础且常用的数据结构之一,其初始化方式多样且各具特点,本文详细讲解Java数组初始化的五种方式,分析其适用场景、优劣势对比及注意事项,帮助避免常见陷阱... 目录1. 静态初始化:简洁但固定代码示例核心特点适用场景注意事项2. 动态初始化:灵活但需手动管理代

python中各种常见文件的读写操作与类型转换详细指南

《python中各种常见文件的读写操作与类型转换详细指南》这篇文章主要为大家详细介绍了python中各种常见文件(txt,xls,csv,sql,二进制文件)的读写操作与类型转换,感兴趣的小伙伴可以跟... 目录1.文件txt读写标准用法1.1写入文件1.2读取文件2. 二进制文件读取3. 大文件读取3.1

Java使用SLF4J记录不同级别日志的示例详解

《Java使用SLF4J记录不同级别日志的示例详解》SLF4J是一个简单的日志门面,它允许在运行时选择不同的日志实现,这篇文章主要为大家详细介绍了如何使用SLF4J记录不同级别日志,感兴趣的可以了解下... 目录一、SLF4J简介二、添加依赖三、配置Logback四、记录不同级别的日志五、总结一、SLF4J

使用Python实现一个优雅的异步定时器

《使用Python实现一个优雅的异步定时器》在Python中实现定时器功能是一个常见需求,尤其是在需要周期性执行任务的场景下,本文给大家介绍了基于asyncio和threading模块,可扩展的异步定... 目录需求背景代码1. 单例事件循环的实现2. 事件循环的运行与关闭3. 定时器核心逻辑4. 启动与停

基于Python实现读取嵌套压缩包下文件的方法

《基于Python实现读取嵌套压缩包下文件的方法》工作中遇到的问题,需要用Python实现嵌套压缩包下文件读取,本文给大家介绍了详细的解决方法,并有相关的代码示例供大家参考,需要的朋友可以参考下... 目录思路完整代码代码优化思路打开外层zip压缩包并遍历文件:使用with zipfile.ZipFil

Python处理函数调用超时的四种方法

《Python处理函数调用超时的四种方法》在实际开发过程中,我们可能会遇到一些场景,需要对函数的执行时间进行限制,例如,当一个函数执行时间过长时,可能会导致程序卡顿、资源占用过高,因此,在某些情况下,... 目录前言func-timeout1. 安装 func-timeout2. 基本用法自定义进程subp

Python实现word文档内容智能提取以及合成

《Python实现word文档内容智能提取以及合成》这篇文章主要为大家详细介绍了如何使用Python实现从10个左右的docx文档中抽取内容,再调整语言风格后生成新的文档,感兴趣的小伙伴可以了解一下... 目录核心思路技术路径实现步骤阶段一:准备工作阶段二:内容提取 (python 脚本)阶段三:语言风格调

Python结合PyWebView库打造跨平台桌面应用

《Python结合PyWebView库打造跨平台桌面应用》随着Web技术的发展,将HTML/CSS/JavaScript与Python结合构建桌面应用成为可能,本文将系统讲解如何使用PyWebView... 目录一、技术原理与优势分析1.1 架构原理1.2 核心优势二、开发环境搭建2.1 安装依赖2.2 验

一文详解如何在Python中从字符串中提取部分内容

《一文详解如何在Python中从字符串中提取部分内容》:本文主要介绍如何在Python中从字符串中提取部分内容的相关资料,包括使用正则表达式、Pyparsing库、AST(抽象语法树)、字符串操作... 目录前言解决方案方法一:使用正则表达式方法二:使用 Pyparsing方法三:使用 AST方法四:使用字

Python列表去重的4种核心方法与实战指南详解

《Python列表去重的4种核心方法与实战指南详解》在Python开发中,处理列表数据时经常需要去除重复元素,本文将详细介绍4种最实用的列表去重方法,有需要的小伙伴可以根据自己的需要进行选择... 目录方法1:集合(set)去重法(最快速)方法2:顺序遍历法(保持顺序)方法3:副本删除法(原地修改)方法4: