返回

LeetCode-62 不同路径(I):算法详解与代码实现

前端

LeetCode-62 不同路径(I):算法讲解与代码实现

导言

在算法学习中,LeetCode是一块算法爱好者们的训练宝地。作为LeetCode题目讲解专栏的第一篇,我们精选了较为基础但极具代表性的「62. 不同路径(I)」题目,带你领略算法之美。本篇将为你提供清晰的算法讲解和高效的代码实现,助你轻松迈出算法之旅的第一步。

题目

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

为了方便理解,这里有一个3x7的网格:

Start ----->  Finish
|    |        |     |
|    |        |     |
|    |        |     |

在这个网格中,一共有28条不同的路径。

算法讲解

动态规划

动态规划是解决此类问题的经典算法范式。它的核心思想是将问题分解为更小的子问题,并逐步求解这些子问题,最终得到问题的整体解。对于本题,我们可以将网格划分为子网格,并求出每个子网格到达右下角的路径数,最后将所有子网格的路径数相加即可得到问题的整体解。

子问题定义

dp[i][j]表示机器人从网格的(i, j)位置到达右下角的路径数。则问题可以分解为如下子问题:

  • dp[i][j] = dp[i+1][j] + dp[i][j+1],其中(i, j)不为右下角

  • dp[m][n] = 1,即当机器人到达右下角时,路径数为1

状态转移方程

由子问题定义可知,状态转移方程为:

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

代码实现

JavaScript

/**
 * @param {number} m
 * @param {number} n
 * @return {number}
 */
const uniquePaths = (m, n) => {
  // 初始化动态规划表
  const dp = new Array(m).fill(0).map(() => new Array(n).fill(0));
  
  // 初始化右边界和下边界
  for (let i = 0; i < m; i++) {
    dp[i][n - 1] = 1;
  }
  for (let j = 0; j < n; j++) {
    dp[m - 1][j] = 1;
  }
  
  // 动态规划求解
  for (let i = m - 2; i >= 0; i--) {
    for (let j = n - 2; j >= 0; j--) {
      dp[i][j] = dp[i + 1][j] + dp[i][j + 1];
    }
  }
  
  // 返回左上角的路径数
  return dp[0][0];
};

复杂度分析

时间复杂度

由于动态规划表的大小为m×n,每个元素的计算只涉及其相邻元素,因此时间复杂度为O(m×n)。

空间复杂度

动态规划表的大小为m×n,因此空间复杂度为O(m×n)。

总结

「62. 不同路径(I)」题目是算法入门中的经典问题,通过动态规划算法可以高效地求解。本篇讲解从算法原理到代码实现,详细阐述了问题的解决思路和步骤,希望能帮助你更好地理解算法并提升算法能力。欢迎在评论区留言讨论,一起探索算法世界的奥妙。