-
题目描述:
-
一个机器人位于一个
m x n
网格的左上角 (起始点在下图中标记为 “Start” )。 -
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
-
问总共有多少条不同的路径?
-
-
-
解题思想:
-
动态规划:
-
动态规划是一种将复杂问题分解成更小的子问题并存储子问题解决方案的方法。在这个问题中,我们通过计算从起始点到每个位置的不同路径数目来解决问题。
-
具体来说,我们定义一个二维数组
dp
,其中dp[i][j]
表示从起始点到达网格的位置(i, j)
的不同路径数目。我们首先初始化第一行和第一列,因为在这些位置上,机器人只能向右或向下移动,所以到达这些位置的路径数都是1。然后,对于其余的位置(i, j)
,到达它的路径数是从上面一格(i-1, j)
和左边一格(i, j-1)
的路径数之和,因为机器人只能向下或向右移动。最后,返回dp[m-1][n-1]
,即到达右下角的路径数。 -
这种方法的时间复杂度是 O(m * n),空间复杂度也是 O(m * n),因为我们需要一个二维数组来存储不同位置的路径数目。
-
-
解题步骤:
-
1. 定义一个二维数组
cur
, - 其中
cur[i][j]
表示从起始点到达网格的位置(i, j)
的不同路径数目。 初始化第一行和第一列,因为在这些位置上,机器人只能向右或向下移动,所以到达这些位置的路径数都是1。-
int[][] cur = new int[m][n]; for (int i = 1; i < m; i++) cur[i][0] = 1; // 第一列元素为 1 for (int j = 1; j < n; j++) cur[0][j] = 1; // 第一行元素为 1
-
-
2. 遍历二维数组,
-
对于其余的位置
(i, j)
,到达它的路径数是从上面一格(i-1, j)
和左边一格(i, j-1)
的路径数之和,因为机器人只能向下或向右移动。-
for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { cur[i][j] = cur[i - 1][j] + cur[i][j - 1]; } }
-
-
3. 返回最终结果:
-
return cur[m - 1][n - 1];
-
-
以下是完整代码:
-
class Solution { public int uniquePaths(int m, int n) { int[][] cur = new int[m][n]; for (int i = 0; i < m; i++) cur[i][0] = 1; // 第一列元素为 1 for (int j = 0; j < n; j++) cur[0][j] = 1; // 第一行元素为 1 for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { cur[i][j] = cur[i - 1][j] + cur[i][j - 1]; } } return cur[m - 1][n - 1]; } }
-
进阶:
- 进一步优化代码, 减少空间分配
- 不难发现, 我们建立的矩阵, 所有空间只使用了一次, 可以重复利用空间来减小空间复杂度
-
这里我们不妨利用滚动数组(Rolling Array)来降低空间复杂度。滚动数组是一种优化技巧,用于减少动态规划算法中所需的额外空间。
-
在代码中,我们可以定义一个长度为
n
的数组cur
,并将其所有元素初始化为1。然后,我们遍历从第二行开始的每一行(i
从1到m-1
)。在每一行的遍历过程中,我们更新数组cur
中每个元素的值,使其等于其本身加上其左边元素的值。这样,最终cur[n-1]
中存储的就是到达右下角的路径数目。 -
这种方法只使用了长度为
n
的数组来存储路径数目,因此空间复杂度为 O(n)。时间复杂度仍然是 O(m * n),因为我们仍然需要遍历整个网格。
-
-
下面是代码实现:
-
class Solution { public int uniquePaths(int m, int n) { int[] cur = new int[n]; Arrays.fill(cur, 1); for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { cur[j] += cur[j - 1]; } } return cur[n - 1]; } }
-
-
以上是本篇文章的全部内容, 感想观看.
-
-
-