题目
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
问总共有多少条不同的路径?
题解一:递归
public int uniquePaths(int m, int n) {
if( m == 1) {
return 1;
}
if(n == 1) {
return 1;
}
return this.uniquePaths(m-1, n) + this.uniquePaths(m, n-1);
}
题解二:动态规划(自底向上)
public int uniquePaths(int m, int n) {
int[][] matrix = new int[m][n];
// 初始化矩阵
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
matrix[i][j] = 0;
}
}
// 初始化最后一列
for(int i = 0; i < m; i++) {
matrix[i][n-1] = 1;
}
// 初始化最后一行
for(int j = 0; j < n; j++) {
matrix[m-1][j] = 1;
}
// 自底向上计算
for(int i = m-2; i >= 0; i--) {
for(int j = n-2; j >=0; j--) {
matrix[i][j] = matrix[i+1][j] + matrix[i][j+1];
}
}
return matrix[0][0];
}
题解三:组合计算
机器人总共需要移动 m+n-2 步,其中 m-1 步向下走, n-1 步向右走。因此,我们仅需寻找出在全部移动的 m+n-2 步中,哪些步是向下走。哪些步是往右走的。
因此,该问题优化为求解 C(m+n-2, m-1) 的组合数问题。
更进一步优化为计算: C(m+n-2, min(m-1. n-1))
具体代码为:
public int uniquePaths(int m, int n) {
long son = 1;
long mother = 1;
int up = m-1;
int down = m+n-2;
up = Math.min(up, (down - up));
for(int i = up; i > 0; i--) {
son *= down;
mother *= i;
down--;
}
return (int)(son/mother);
}
注:此处应使用 long 类型进行计算,否则会数据溢出。