有个问题怎么也想不通,一下午时间快过去了依旧毫无进展,是时候换换心情刷个题提提神了。。打开LeetCode随机点了个62题,题目如下:
机器人位于一个 m x n 网格的左上角, 在下图中标记为“Start” (开始)。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角,在下图中标记为“Finish”(结束)。
问有多少条不同的路径?
例如,上图是一个3 x 7网格。有多少可能的路径?
注意: m 和 n 的值均不超过 100。
我的第一想法是递归,非常简单:
// public static int uniquePaths(int m, int n) {
// if ((m == 1) || (n == 1)){
// return 1;
// }
// return uniquePaths(m, n - 1) + uniquePaths(m - 1, n);
// }
结果提交的时候超时了,也是醉了,然后就想了想别的思路。其实说起来也不难,就是把路径都放到一个二维数组里,这样就避免了递归中大量的重复运算。我们可以轻易的找到一个规律:从起点到m,n的路径=从起点到m,n-1的路径+从起点到m-1,n的路径,所以就有了如下代码:
public static int uniquePaths(int m, int n) {
int[][] ways = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (i==0 || j==0) {
ways[i][j] = 1;
}
else {
ways[i][j] = ways[i-1][j] + ways[i][j-1];
}
}
}
return ways[m-1][n-1];
}
这次提交倒是通过了,不过看起来还是豚豚的,网上看了看某个大哥(dai guo)写的,发现果然还有个更好的方法(链接如下点击打开链接),而且最跳的是我的这两种方法也在他的这个博客里有,而且一毛一样(我真的没ctrl+C,好气啊)。不说了,说下他的最优方法:
引自原文:这种优化是对上述方法空间的一种优化,使得空间复杂度从原来的 O(n*m)下降为 O(n)。对于起点到点(i,j)的路径总数:ways[j]= 起点到点(i-1, j) 的路径总数:ways[j] + 起点到点(i, j-1)的路径总数 ways[j-1],于是我们就得到递推式:ways[j] = ways[j] + ways[j-1]
故有代码:
public class Solution {
public int uniquePaths(int m, int n) {
int[] ways = new int[n];
ways[0] = 1;
for(int i = 0; i < m; i++)
for (int j = 1; j < n; j++)
ways[j] += ways[j-1];
return ways[n-1];
}
}