Link: https://oj.leetcode.com/problems/unique-paths/
Approach I: Simple DFS
Time: O(n^4), Space: O(n)//why?
public class Solution {
//dfs
//the #paths at (m,n) can only come from above(m-1,n) or left(m,n-1)
//note: i belongs to [1, m], j belongs to [1, n] (not[0, m-1], [0, n-1])
public int uniquePaths(int m, int n) {
if(m <1 || n <1) return 0;
if(m == 1 && n == 1) return 1;
return uniquePaths(m-1, n) + uniquePaths(m, n-1);
}
}
Approach II: 备忘录法(自顶向下)//how to code from Dai's C++ Code?
Approach III: DP (Dai's code) 自底向上
(1) DP with O(n_2) space (fastest overall algorithms)
public class Solution {
public int uniquePaths(int m, int n) {
int[][] matrix = new int[m][n];
for(int i = 0; i < m; i++){
matrix[i][0] = 1;
}
for(int i = 0; i < n; i++){
matrix[0][i] = 1;
}
for(int i = 1; i < m; i++){
for(int j = 1; j < n; j++){
matrix[i][j] = matrix[i-1][j] + matrix[i][j-1];
}
}
return matrix[m-1][n-1];
}
}
(2) DP with O(n) space
Time: O(m*n), Space: O(n)
public class Solution {
//DP with O(n)
//we only need to save the previous row
public int uniquePaths(int m, int n) {
int[] f = new int[n];
f[0] = 1;//the first col is initialized to all ones
for(int i = 0; i < m; i++){
for(int j = 1; j <n; j++){
// 左边的f[j],表示更新后的f[j],与公式中的f[i[[j] 对应
// 右边的f[j],表示老的f[j],与公式中的f[i-1][j] 对应
f[j] = f[j] + f[j-1];
}
}
return f[n-1];
}
}
Approach IV Combinations Math
http://blog.csdn.net/linhuanmars/article/details/22126357
Time: O(min(m, n)), Space: O(1)
public class Solution {
//Math. Choose (m-1) "down" steps out of (m+n-2) total steps
public int uniquePaths(int m, int n) {
double denom = 1;
double numer = 1;
double small = m < n? m-1 : n-1;
double large = m < n? n-1 : m-1;
//we reduced both denominator and numerator by large
//so (small)! is left on the demominator
for(int i = 1; i <= small; i++){
denom *= i;
numer*= small + large + 1 - i;//denominator is a factorial starting with m+n-2
}
return (int)(numer/denom);
}
}