「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战」
前言
笔者除了大学时期选修过《算法设计与分析》和《数据结构》还是浑浑噩噩度过的(当时觉得和编程没多大关系),其他时间对算法接触也比较少,但是随着开发时间变长对一些底层代码/处理机制有所接触越发觉得算法的重要性,所以决定开始系统的学习(主要是刷力扣上的题目)和整理,也希望还没开始学习的人尽早开始。
系列文章收录《算法》专栏中。
问题描述
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
示例 1:
输入:m = 3, n = 7
输出:28
示例 2:
输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右
3. 向下 -> 向右 -> 向下
示例 3:
输入:m = 7, n = 3
输出:28
示例 4:
输入:m = 3, n = 3
输出:6
提示:
- 1 <= m, n <= 100
- 题目数据保证答案小于等于 2 * 10^9
剖析
这道题用到了动态规划,可以用f(i,j)表示从左上角走到(i,j)的路径数量,i为题目的m,j为题目的n,因为机器人已经在左上角的第一个格子中,所以其实相当于已经在(1,1)上,所以结果为f(m-1,n-1)。
那么怎么求f(m-1,n-1)表示的路径是多少呢?
- 我们先看下比较特殊的,到最上面一行或者到最右边一列的路径是不是不管哪一格都是为1?那么我们就可以得出f(0,j)=1和f(i,0)=1。
- 如果我们向下走一步会从(i-1,j)走过来,如果我们向右走一步会从(i,j-1)走过来,所以可以得出动态规划转移方程:f(i,j)=f(i-1,j)+f(i,j-1)。
- 我们可以发现要求出f(i,j)只要求出它走到上面格子的路径f(i-1,j)和走到左边格子路径f(i,j-1之和就行了。我们可以试下,比如m=2 n=2,f(1,1)=f(0,1)+f(1,0)=2,再比如m=3 n=2,f(2,1)=f(1,1)+f(2,0)=3。
解这道题给我的感觉很像递归:求出外层的东西需要先到内层,先分后总。然后加上特殊边界值进而归纳总结出的结果。
所以代码如下
代码
public int uniquePaths(int m, int n) {
int[][] f = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (i == 0) {
f[i][j] = 1;
continue;
}
if (j == 0) {
f[i][j] = 1;
continue;
}
f[i][j] = f[i - 1][j] + f[i][j - 1];
}
}
return f[m - 1][n - 1];
}