动态规划典型例题。
首先,把每一行每一列的元素初始化为1,因为从起点开始直接走就是一条路径。然后记准平面常用表示的坐标上下左右分别对应y-1、y+1、x-1、x+1,然后要到右下角,那去到目标点就是从左边或上方来,显然就是找到旁边的路径总和就是到该点的路径总数了,循环遍历到要走的步数。
时间复杂度O(mn),空间复杂度O(mn)。
class Solution {
public int uniquePaths(int m, int n) {
int[][] f = new int[m][n];
for (int i = 0; i < m; i++) {
f[i][0] = 1;
}
for (int j = 0; j < n; j++) {
f[0][j] = 1;
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
f[i][j] = f[i - 1][j] + f[i][j - 1];
}
}
return f[m - 1][n - 1];
}
}
[1, 1, 1],
[1, 2, 3],
[1, 3, 6]
在数组的内循环中,每一个点由同一行不同列与上一行同列的得到,说明在遍历行时有一个变量是不用作改变的,这个二维数组可以作一个优化,滚动数组化为一维数组。
class Solution {
public int uniquePaths(int m, int n) {
int[] f = new int[n];
for (int i = 0; i < n; i++) {
f[i] = 1;
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
f[j] += f[j - 1];
}
}
return f[n - 1];
}
}
可以看到相似的代码部分为 f[i][j] = f[i - 1][j] + f[i][j - 1];改到了f[j] += f[j - 1];即f[j] = f[j] + f[j - 1],而等式的f[j] + f[j - 1]由于f[j]在这里还没做更新,因此所对应的就是上一行的f[j],而f[j - 1]是在内循环的前一步做了这一行的更新,所以是对应的。滚动数组优化后时间复杂度O(mn),空间复杂度O(n),节省了空间开销。