0062.不同路径
参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
# 62.不同路径 [力扣题目链接](https://leetcode.cn/problems/unique-paths/) 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的路径? 示例 1:  * 输入:m = 3, n = 7 * 输出:28 示例 2: * 输入:m = 2, n = 3 * 输出:3 解释: 从左上角开始,总共有 3 条路径可以到达右下角。 1. 向右 -> 向右 -> 向下 2. 向右 -> 向下 -> 向右 3. 向下 -> 向右 -> 向右 示例 3: * 输入:m = 7, n = 3 * 输出:28 示例 4: * 输入:m = 3, n = 3 * 输出:6 提示: * 1 <= m, n <= 100 * 题目数据保证答案小于等于 2 * 10^9 ## 算法公开课 **[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[动态规划中如何初始化很重要!| LeetCode:62.不同路径](https://www.bilibili.com/video/BV1ve4y1x7Eu/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。 ## 思路 ### 深搜 这道题目,刚一看最直观的想法就是用图论里的深搜,来枚举出来有多少种路径。 注意题目中说机器人每次只能向下或者向右移动一步,那么其实**机器人走过的路径可以抽象为一棵二叉树,而叶子节点就是终点!** 如图举例:  此时问题就可以转化为求二叉树叶子节点的个数,代码如下:class Solution {
private:
int dfs(int i, int j, int m, int n) {
if (i > m || j > n) return 0; // 越界了
if (i == m && j == n) return 1; // 找到一种方法,相当于找到了叶子节点
return dfs(i + 1, j, m, n) + dfs(i, j + 1, m, n);
}
public:
int uniquePaths(int m, int n) {
return dfs(1, 1, m, n);
}
};
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m, vector<int>(n, 0));
for (int i = 0; i < m; i++) dp[i][0] = 1;
for (int j = 0; j < n; j++) dp[0][j] = 1;
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
}
};
class Solution {
public:
int uniquePaths(int m, int n) {
vector<int> dp(n);
for (int i = 0; i < n; i++) dp[i] = 1;
for (int j = 1; j < m; j++) {
for (int i = 1; i < n; i++) {
dp[i] += dp[i - 1];
}
}
return dp[n - 1];
}
};
class Solution {
public:
int uniquePaths(int m, int n) {
int numerator = 1, denominator = 1;
int count = m - 1;
int t = m + n - 2;
while (count--) numerator *= (t--); // 计算分子,此时分子就会溢出
for (int i = 1; i <= m - 1; i++) denominator *= i; // 计算分母
return numerator / denominator;
}
};
class Solution {
public:
int uniquePaths(int m, int n) {
long long numerator = 1; // 分子
int denominator = m - 1; // 分母
int count = m - 1;
int t = m + n - 2;
while (count--) {
numerator *= (t--);
while (denominator != 0 && numerator % denominator == 0) {
numerator /= denominator;
denominator--;
}
}
return numerator;
}
};
/**
* 1. 确定dp数组下标含义 dp[i][j] 到每一个坐标可能的路径种类
* 2. 递推公式 dp[i][j] = dp[i-1][j] dp[i][j-1]
* 3. 初始化 dp[i][0]=1 dp[0][i]=1 初始化横竖就可
* 4. 遍历顺序 一行一行遍历
* 5. 推导结果 。。。。。。。。
*
* @param m
* @param n
* @return
*/
public static int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
//初始化
for (int i = 0; i < m; i++) {
dp[i][0] = 1;
}
for (int i = 0; i < n; i++) {
dp[0][i] = 1;
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = dp[i-1][j]+dp[i][j-1];
}
}
return dp[m-1][n-1];
}
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)
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
# 创建一个二维列表用于存储唯一路径数
dp = [[0] * n for _ in range(m)]
# 设置第一行和第一列的基本情况
for i in range(m):
dp[i][0] = 1
for j in range(n):
dp[0][j] = 1
# 计算每个单元格的唯一路径数
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]
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
# 创建一个一维列表用于存储每列的唯一路径数
dp = [1] * n
# 计算每个单元格的唯一路径数
for j in range(1, m):
for i in range(1, n):
dp[i] += dp[i - 1]
# 返回右下角单元格的唯一路径数
return dp[n - 1]
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
numerator = 1 # 分子
denominator = m - 1 # 分母
count = m - 1 # 计数器,表示剩余需要计算的乘积项个数
t = m + n - 2 # 初始乘积项
while count > 0:
numerator *= t # 计算乘积项的分子部分
t -= 1 # 递减乘积项
while denominator != 0 and numerator % denominator == 0:
numerator //= denominator # 约简分子
denominator -= 1 # 递减分母
count -= 1 # 计数器减1,继续下一项的计算
return numerator # 返回最终的唯一路径数
func uniquePaths(m int, n int) int {
dp := make([][]int, m)
for i := range dp {
dp[i] = make([]int, n)
dp[i][0] = 1
}
for j := 0; j < n; j++ {
dp[0][j] = 1
}
for i := 1; i < m; i++ {
for j := 1; j < n; j++ {
dp[i][j] = dp[i-1][j] + dp[i][j-1]
}
}
return dp[m-1][n-1]
}
var uniquePaths = function(m, n) {
const dp = Array(m).fill().map(item => Array(n))
for (let i = 0; i < m; ++i) {
dp[i][0] = 1
}
for (let i = 0; i < n; ++i) {
dp[0][i] = 1
}
for (let i = 1; i < m; ++i) {
for (let j = 1; j < n; ++j) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
}
}
return dp[m - 1][n - 1]
};
/**
* @param {number} m
* @param {number} n
* @return {number}
*/
var uniquePaths = function(m, n) {
let dp = new Array(m).fill(1).map(() => new Array(n).fill(1));
// dp[i][j] 表示到达(i,j) 点的路径数
for (let i=1; i<m; i++) {
for (let j=1; j< n;j++) {
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[m-1][n-1];
};
function uniquePaths(m: number, n: number): number {
/**
dp[i][j]: 到达(i, j)的路径数
dp[0][*]: 1;
dp[*][0]: 1;
...
dp[i][j]: dp[i - 1][j] + dp[i][j - 1];
*/
const dp: number[][] = new Array(m).fill(0).map(_ => []);
for (let i = 0; i < m; i++) {
dp[i][0] = 1;
}
for (let i = 0; i < n; i++) {
dp[0][i] = 1;
}
for (let i = 1; i < m; i++) {
for (let j = 1; j < n; j++) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
};
impl Solution {
pub fn unique_paths(m: i32, n: i32) -> i32 {
let (m, n) = (m as usize, n as usize);
let mut dp = vec![vec![1; n]; m];
for i in 1..m {
for j in 1..n {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
dp[m - 1][n - 1]
}
}
//初始化dp数组
int **initDP(int m, int n) {
//动态开辟dp数组
int **dp = (int**)malloc(sizeof(int *) * m);
int i, j;
for(i = 0; i < m; ++i) {
dp[i] = (int *)malloc(sizeof(int) * n);
}
//从0,0到i,0只有一种走法,所以dp[i][0]都是1,同理dp[0][j]也是1
for(i = 0; i < m; ++i)
dp[i][0] = 1;
for(j = 0; j < n; ++j)
dp[0][j] = 1;
return dp;
}
int uniquePaths(int m, int n){
//dp数组,dp[i][j]代表从dp[0][0]到dp[i][j]有几种走法
int **dp = initDP(m, n);
int i, j;
//到达dp[i][j]只能从dp[i-1][j]和dp[i][j-1]出发
//dp[i][j] = dp[i-1][j] + dp[i][j-1]
for(i = 1; i < m; ++i) {
for(j = 1; j < n; ++j) {
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
int result = dp[m-1][n-1];
free(dp);
return result;
}
int uniquePaths(int m, int n){
int i, j;
// 初始化dp数组
int *dp = (int*)malloc(sizeof(int) * n);
for (i = 0; i < n; ++i)
dp[i] = 1;
for (j = 1; j < m; ++j) {
for (i = 1; i < n; ++i) {
// dp[i]为二维数组解法中dp[i-1][j]。dp[i-1]为二维数组解法中dp[i][j-1]
dp[i] += dp[i - 1];
}
}
return dp[n - 1];
}
object Solution {
def uniquePaths(m: Int, n: Int): Int = {
var dp = Array.ofDim[Int](m, n)
for (i <- 0 until m) dp(i)(0) = 1
for (j <- 1 until n) dp(0)(j) = 1
for (i <- 1 until m; j <- 1 until n) {
dp(i)(j) = dp(i - 1)(j) + dp(i)(j - 1)
}
dp(m - 1)(n - 1)
}
}