题目描述(中等难度)
机器人从左上角走到右下角,只能向右或者向下走。输出总共有多少种走法。
解法一 递归
求 ( 0 , 0 ) 点到( m - 1 , n - 1) 点的走法。
(0,0)点到(m - 1 , n - 1) 点的走法等于(0,0)点右边的点 (1,0)到(m - 1 , n - 1)的走法加上(0,0)点下边的点(0,1)到(m - 1 , n - 1)的走法。
而左边的点(1,0)点到(m - 1 , n - 1) 点的走法等于(2,0) 点到(m - 1 , n - 1)的走法加上(1,1)点到(m - 1 , n - 1)的走法。
下边的点(0,1)点到(m - 1 , n - 1) 点的走法等于(1,1)点到(m - 1 , n - 1)的走法加上(0,2)点到(m - 1 , n - 1)的走法。
然后一直递归下去,直到 (m - 1 , n - 1) 点到(m - 1 , n - 1) ,返回 1。
public class Unique_Paths {
public static int uniquepaths(int m, int n) {
return getans(0,0,m-1,n-1,0);
}
private static int getans(int x, int y, int m, int n, int num) {
if(x==m & y==n) return 1;
int n1=0;
int n2=0;
if(x+1<=m) {
n1=getans(x+1,y,m,n,num);
}
if(y+1<=n) {
n2=getans(x,y+1,m,n,num);
}
return n1+n2;
}
public static void main(String args[]) {
int m=3,n=2;
int ans=uniquepaths(m,n);
System.out.println(ans);
}
}
现在在leetcode上已经报超时。
解法二 动态规划
public class Unique_Paths3 {
public static int uniquePaths(int m, int n) {
int[][] res=new int[m][n];
for(int i=0;i<m;i++) {
res[i][0]=1;
}
for(int j=0;j<n;j++) {
res[0][j]=1;
}
for(int i=1;i<m;i++) {
for(int j=1;j<n;j++) {
res[i][j]=res[i-1][j]+res[i][j-1];
}
}
return res[m-1][n-1];
}
public static void main(String args[]) {
int m=3,n=2;
int ans=uniquePaths(m,n);
System.out.println(ans);
}
}
时间复杂度:O(m*n)。
空间复杂度:O(m*n)。
代码可以更加简化
class Solution {
public int uniquePaths(int m, int n) {
int[][] res =new int[m][n];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(i==0 && j==0) res[i][j]=1;
else if(i==0) res[i][j]=1;
else if(j==0) res[i][j]=1;
else res[i][j]=res[i-1][j]+res[i][j-1];
}
}
return res[m-1][n-1];
}
}
可以进一步优化。
public class Unique_Paths4 {
public static int uniquePaths(int m, int n) {
int[] dp = new int[n];
for (int i = 0; i < n; i++) {
dp[i] = 1;
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[j] = dp[j] + dp[j - 1];
}
}
return dp[(n - 1)];
}
public static void main(String args[]) {
int m=3,n=2;
int ans=uniquePaths(m,n);
System.out.println(ans);
}
}
时间复杂度:O(m*n)。
空间复杂度:O(n)。
解法三 公式
我们用 R 表示向右,D 表示向下,然后把所有路线写出来,就会发现神奇的事情了。
R R R D D
R R D D R
R D R D R
……
从左上角,到右下角,总会是 3 个 R,2 个 D,只是出现的顺序不一样。所以求解法,本质上是求了组合数,N = m + n - 2,也就是总共走的步数。 k = m - 1,也就是向下的步数,D 的个数。所以总共的解就是 [公式] 。
public int uniquePaths(int m, int n) {
int N = n + m - 2;
int k = m - 1;
long res = 1;
for (int i = 1; i <= k; i++)
res = res * (N - k + i) / i;
return (int) res;
}
时间复杂度:O(m)。
空间复杂度:O(1)。