牛客题解 | 不同路径的数目(一)

news/2025/2/25 15:57:48/文章来源:https://www.cnblogs.com/wc529065/p/18736512

题目

题目链接

题目主要信息:
  • 给定一个\(m*n\)的矩阵,要求从矩阵的左上角走到右下角的不同路径数量
  • 每次只能往下或者往右走
举一反三:

学习完本题的思路你可以解决如下题目:

BM68.矩阵的最小路径和

方法一:递归(推荐使用)

知识点:递归

递归是一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。因此递归过程,最重要的就是查看能不能讲原本的问题分解为更小的子问题,这是使用递归的关键。

思路:

首先我们在左上角第一个格子的时候,有两种行走方式:如果向右走,相当于后面在一个\((n-1)*m\)的矩阵中查找从左上角到右下角的不同路径数;而如果向下走,相当于后面在一个\(n*(m-1)\)的矩阵中查找从左上角到右下角不同的路径数。而\((n-1)*m\)的矩阵与\(n*(m-1)\)的矩阵都是\(n*m\)矩阵的子问题,因此可以使用递归。

具体做法:

  • step 1:(终止条件) 当矩阵变长n减少到1的时候,很明显只能往下走,没有别的选择了,只有1条路径;同理m减少到1时也是如此。因此此时返回数量为1.
  • step 2:(返回值) 对于每一级都将其两个子问题返回的结果相加返回给上一级。
  • step 3:(本级任务) 每一级都有向下或者向右两种路径选择,分别进入相应分支的子问题。

图示:

alt

Java实现代码:

import java.util.*;
public class Solution {public int uniquePaths (int m, int n) {//矩阵只要有一条边为1,路径数就只有一种了if(m == 1 || n == 1) return 1;//两个分支return uniquePaths(m - 1, n) + uniquePaths(m, n - 1); }
}

C++实现代码:

class Solution {
public:int uniquePaths(int m, int n) {//矩阵只要有一条边为1,路径数就只有一种了if(m == 1 || n == 1) return 1;//两个分支return uniquePaths(m - 1, n) + uniquePaths(m, n - 1); }
};

Python代码实现:(Python版本超时,不能完全通过)

import sys
#设置递归深度
sys.setrecursionlimit(100000) 
class Solution:def uniquePaths(self , m: int, n: int) -> int:#矩阵只要有一条边为1,路径数就只有一种了if m == 1 or n == 1: return 1else: #两个分支return self.uniquePaths(m - 1, n) + self.uniquePaths(m, n - 1)

复杂度分析:

  • 时间复杂度:\(O(mn)\),其中\(m\)\(n\)分别为矩阵的两边长,递归过程对于每个\(m\)最多都要经过每一种\(n\)
  • 空间复杂度:\(O(m+n)\),递归栈的最大深度为矩阵两边从\(m\)\(n\)都到了1
方法二:动态规划(扩展思路)

知识点:动态规划

动态规划算法的基本思想是:将待求解的问题分解成若干个相互联系的子问题,先求解子问题,然后从这些子问题的解得到原问题的解;对于重复出现的子问题,只在第一次遇到的时候对它进行求解,并把答案保存起来,让以后再次遇到时直接引用答案,不必重新求解。动态规划算法将问题的解决方案视为一系列决策的结果。

思路:

如果我们此时就在右下角的格子,那么能够到达该格子的路径只能是它的上方和它的左方两个格子,因此从左上角到右下角的路径数应该是从左上角到它的左边格子和上边格子的路径数之和,因此可以动态规划。

具体做法:

  • step 1:用dp[i][j]表示大小为\(i*j\)的矩阵的路径数量,下标从1开始。
  • step 2:(初始条件) 当i或者j为1的时候,代表矩阵只有一行或者一列,因此只有一种路径。
  • step 3:(转移方程) 每个格子的路径数只会来自它左边的格子数和上边的格子数,因此状态转移为\(dp[i][j] = dp[i - 1][j] + dp[i][j - 1]\)

图示:

alt

Java实现代码:

import java.util.*;
public class Solution {public int uniquePaths (int m, int n) {//dp[i][j]表示大小为i*j的矩阵的路径数量int[][] dp = new int[m + 1][n + 1]; for(int i = 1; i <= m; i++){for(int j = 1; j <= n; j++){//只有1行的时候,只有一种路径if(i == 1){ dp[i][j] = 1;continue;}//只有1列的时候,只有一种路径if(j == 1){ dp[i][j] = 1;continue;}//路径数等于左方格子的路径数加上上方格子的路径数dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; }}return dp[m][n];}
}

C++实现代码:

class Solution {
public:int uniquePaths(int m, int n) {//dp[i][j]表示大小为i*j的矩阵的路径数量vector<vector<int> > dp(m + 1, vector<int>(n + 1, 0)); for(int i = 1; i <= m; i++){for(int j = 1; j <= n; j++){//只有1行的时候,只有一种路径if(i == 1){ dp[i][j] = 1;continue;}//只有1列的时候,只有一种路径if(j == 1){ dp[i][j] = 1;continue;}//路径数等于左方格子的路径数加上上方格子的路径数dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; }}return dp[m][n];}
};

Python代码实现:

class Solution:def uniquePaths(self , m: int, n: int) -> int:#dp[i][j]表示大小为i*j的矩阵的路径数量dp = [[0] * (n + 1) for i in range(m + 1)] for i in range(1, m + 1):for j in range(1, n + 1):#只有1行的时候,只有一种路径if i == 1: dp[i][j] = 1continue#只有1列的时候,只有一种路径if j == 1: dp[i][j] = 1continue#路径数等于左方格子的路径数加上上方格子的路径数dp[i][j] = dp[i - 1][j] + dp[i][j - 1] return dp[m][n]

复杂度分析:

  • 时间复杂度:\(O(mn)\),其中\(m\)\(n\)分别为矩阵的两边长,两层遍历填充整个dp数组
  • 空间复杂度:\(O(mn)\),辅助空间dp数组为二维数组
方法三:组合数学(扩展思路)

思路:

从矩阵左上角走到矩阵右下角,总共需要往下走\(m-1\)步,往右走\(n-1\)步,不同的走法路径在于往下和往右的组合情况,即在一堆往下和往右的序列中,每种排列的情况,序列一共有\(m+n-2\)个位置,选择其中\(n-1\)个位置作为往下,即不同的走法有\(C^{n-1}_{m+n-2}=\frac{(m+n-2)!}{(n-1)!(m-1)!}\)种情况。

具体做法:

  • step 1:分子分母从1开始;
  • step 2:按照公式累乘相除。

Java实现代码:

import java.util.*;
public class Solution {public int uniquePaths (int m, int n) {//防止溢出long res = 1; for(int i = 1; i < n; i++)//根据公式计算res = res * (m + i - 1) / i; return (int)res;}
}

C++实现代码:

class Solution {
public:int uniquePaths(int m, int n) {//防止溢出long res = 1; for(int i = 1; i < n; i++)//根据公式计算res = res * (m + i - 1) / i; return (int)res;}
};

Python代码实现:

class Solution:#计算阶乘def fun(self, n: int) -> int: sum = 1#连乘for i in range(1, n + 1):sum *= ireturn sumdef uniquePaths(self , m: int, n: int) -> int:#公式计算return self.fun(m + n - 2) // (self.fun(m - 1) * self.fun(n - 1))

复杂度分析:

  • 时间复杂度:\(O(n)\),计算过程需要从1遍历到n
  • 空间复杂度:\(O(1)\),常数级变量,无额外辅助空间

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/889614.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

牛客题解 | 不用加减乘除做加法

牛客题库题解题目 题目链接 题目的主要信息:题目给出两个数字 我们需要给出两个数字相加的结果 题目要求我们不可以用加减乘除符号 因此与或非运算就是我们可以用的方式举一反三: 学习完本题的思路你可以解决如下题目: JZ15. 二进制中1的个数 JZ56. 数组中只出现一次的两个数…

S2-奥法-法师Mage-奥术-团体-大秘境-专精-天赋-配装-宏

S2毕业装--属性 急速>精通>全能>爆击 急速越高越好。精通的收益略微高于全能。爆击随缘。 --团本/单体天赋(更新时间2月4日)--团本/单体天赋代码 C4DAjd9IgsSkCmGQ8vOmZtyV7YGMbzCmxDMmFDjZGGTzMmBAAAAAgBCACYmZbZZZmJWAAAAAAAALDDzMzMjZYmxYmZMzMjxMG --大秘/AOE天赋…

vue贪吃蛇小游戏

偶然间跟一个前端大佬学习了一个用vue写的贪吃蛇小游戏,一个小demo 感觉挺好玩,就纪录下来了直接全代码 <template><div><div class="title" :class="isShowTitle ? titlebg : "><span>分数:{{ score }}</span></div…

S2-浩劫-恶魔猎手DH-团体-大秘境-专精-天赋-配装-宏

S2毕业装--属性 爆击>精通>急速>全能 爆击和精通越高越好。急速随缘。不要全能。 --团本/单体天赋(更新时间2月1日)--团本/单体天赋代码 CEkAAAAAAAAAAAAAAAAAAAAAAYGMzMzgZmZMmJmZGAAAAAAwsMmxMMGLzMz2sNLjZGmZBLbwysYGDzGTDmZmZwG --大秘/AOE天赋(更新时间2月1日)--…

echart地图合并,并取消边框

1.地图文件编辑mapshaper https://mapshaper.org/ 2.首先将你要合并的地图文件,添加字段标识,name同级添加,名字自定义比如“area”。 举个栗子,我要将崇明区和长兴区合并成一个新区域叫新区,那么就在两个区域下面添加 "area": "新区",3.整…

用Logseq记日报和管理文献

优缺点浅评 Logseq是一款双链笔记软件,其优点结合使用场景概括来说包括开箱即用的极简界面,非常适合用来写日报 灵活的双链,强大的PDF标注,适合构建文献库 使用markdown格式来本地存储笔记,随意备份缺点多端同步功能薄弱,我不知道有没有实现方法,反正很麻烦 没有了 然后…

Python 学习记录(5)

Scikit-Learn 数据 简单介绍:Scikit-Learn 除了完成监督学习和无监督学习之外,还提供了丰富地样本数据集、样本数据生成函数与数据处理方法。 实现机器学习算法地训练、评估与预测。 包含有样本数据集、生成样本数据、特征工程以及数据分割。处理离群值 简单介绍离群值也叫逸…

gao-ji-sou-suo

高级搜索 posted on 2023-01-16 13:14:22 | under 总结 | source 一,前言 所谓高级搜索,就是对于普通的搜索(dfs,bfs,bdfs)进行优化后得到的在空间或时间上更优的算法,比如 A*,迭代加深,IDA*,双向搜索,折半搜索之类的。 二、算法 1.迭代加深 对于一个搜索的问题,如…

csp-s2023-zong-jie

CSP-S2023总结 posted on 2023-10-24 08:16:22 | under 总结 | source day- 忘了。 考了好几场牛客模拟。 gm说只有考好才能参加noip,并让我们早点休息。 所以到家10:40就睡了。 day0 睡到10:30,起床吃饭看电视。 按照gm的要求,从12:00午睡到13:05。 13:15到了,有个不…

惊艳!200MSPS采样率,RK3588F高速AD采集与实时显示案例来了!

科技飞速发展,高速数据采集与实时显示技术成为众多领域的关键需求。今天给大家分享一个基于瑞芯微RK3588J + FPGA的高速AD采集与实时显示案例。适用开发环境如下: Windows开发环境:Windows 7 64bit、Windows 10 64bit Linux开发环境:VMware16.2.5、Ubuntu20.04.6 64bit U-B…

S2-猫德-德鲁伊Druid-野性-团体-大秘境-专精-天赋-配装-宏

S2毕业装--属性 精通>爆击>急速>全能 精通越高越好。爆击收益略微高于急速。不要全能。 --团本/单体天赋(更新时间2月4日)--团本/单体天赋代码 CcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmZb2MzCzYmZb2YsNzMz8AzMAAAAAAbBDDYMzMamxMjZGjZYjBAAAAAAAYAAAAAAmtZWa2mZZDzMDA --大…

自我介绍+5问(朱雅子)

项目 内容这个作业属于哪个课程 软件工程导论这个作业要求在哪里 作业要求文档这个作业的目标 做好本学期学习准备,初步了解“博客园和github”两个网站,熟悉markdowm编辑模式,明确该课程我想要学习什么增强目标感- part1✨🌊 雅子系统 v1.9 🎭 身份解码器个人信息 数字…