A robot is located at the top-left corner of a m x n grid. It can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid.
How many possible unique paths are there?
Java Solution 1 – DFS
A depth-first search solution is pretty straight-forward. However, the time of this solution is too expensive, and it didn’t pass the online judge.
public int uniquePaths(int m, int n) { return dfs(0,0,m,n); } public int dfs(int i, int j, int m, int n){ if(i==m-1 && j==n-1){ return 1; } if(i<m-1 && j<n-1){ return dfs(i+1,j,m,n) + dfs(i,j+1,m,n); } if(i<m-1){ return dfs(i+1,j,m,n); } if(j<n-1){ return dfs(i,j+1,m,n); } return 0; } |
Java Solution 2 – Dynamic Programming
public int uniquePaths(int m, int n) { if(m==0 || n==0) return 0; if(m==1 || n==1) return 1; int[][] dp = new int[m][n]; //left column for(int i=0; i<m; i++){ dp[i][0] = 1; } //top row for(int j=0; j<n; j++){ dp[0][j] = 1; } //fill up the dp table for(int i=1; i<m; i++){ for(int j=1; j<n; j++){ dp[i][j] = dp[i-1][j] + dp[i][j-1]; } } return dp[m-1][n-1]; } |
Java Solution 3 – Dynamic Programming with Memorization
public int uniquePaths(int m, int n) { int[][] mem = new int[m][n]; //init with -1 value for(int i=0; i<m; i++){ for(int j=0; j<n; j++){ mem[i][j]=-1; } } return helper(mem, m-1, n-1); } private int helper(int[][] mem, int m, int n){ //edge has only one path if(m==0||n==0){ mem[m][n]=1; return 1; } if(mem[m][n]!=-1){ return mem[m][n]; } mem[m][n] = helper(mem, m, n-1) + helper(mem, m-1, n); return mem[m][n]; } |
It works and it gives 2 in case 2×2.
Lets check formula:
0) m = 2; n = 2
1) Decrease n and m by one => m = 1; n =1
2) use formula (m+n)! / (m!n!) = (1+1)!/(1!1!)= 2
Lets check the code:
> m–; // => m=1
> n–; // => n=1
if-condition doesn’t work in this case:
> if (m > n) { // in our case m = n = 1
Set variables:
> int divider = 2;
> int result = 1;
Count combinations (loop):
> for (int i = n + m; i > n; i–) { // in our case i = 2; 2 > 1; i–
> result *= i; // => result =2;
While loop doesn’t work in our case. Condition divider <= m (2 while (divider for (int i = n + m; i > n; i–) { // in our case i = 1; 1 > 1; i–
1 > 1 – is false, so for-loop is finished
> return result; // result = 2
So it gives 2.
Does not work!! Take 2×2, Solution is 2, your solution gives 1.
Good point! But there are (m-1)+(n-1) moves. So we need decrease m and n by one and then can use the formula m+n)! / (m!n!)
My algorithm with O(min(m,n)) time complexity and O(1) extra space:
public int uniquePaths(int m, int n) {
m--;
n--;
if (m > n) {
int t = m;
m = n;
n = t;
}
int divider = 2;
int result = 1;
for (int i = n + m; i > n; i--) {
result *= i;
while (divider <= m && result % divider == 0)
result /= divider++;
}
return result;
}
Hi Sansor, as you’ve said this code will work but only for small numbers. Because it is re-calculating same values again and again. Dynamic Programming solution will be much faster.
to compute factorial won’t be a o(1), this will take o(m+n) but still thumbs up for the maths solution!
This code is running perfectly..
public int numberOfPaths(int m, int n) {
if (m == 1 || n == 1) {
return 1;
}
int temp = numberOfPaths(m – 1, n) + numberOfPaths(m, n – 1);
return temp;
}
There’s an O(1) solution. Remember math.
The robot has to make (m+n) moves to get from the top left to the bottom right corner. It must make exactly m moves across and n moves down. Thus, to find the number of possible traversals, consider how many ways the robot can order its m right moves and n down moves. Pick m of the (m+n) to be the right moves, and the rest must be the n down. This is (m+n) choose m = (m+n)! / (m!n!).