Problem :
How many possible unique paths are there?
(project euler problem 15)
The similar question has been asked in Cracking the coding interview: Here we have to count the unique paths, but there we have to find the unique paths.
Example
Below is an example of 4x4 grid. Here from moving top-left to bottom right corner, we will have 20 unique paths.
Solution
Since we know that one can only move either down or right at any point in time so one can reach to cell (i,j) only from 2 possible locations:
Method 1 - backtracking
The most direct way is to write code that traverses each possible path, which can be done using backtracking. When you reach row=m and col=n, you know you’ve reached the bottom-right corner, and there is one additional unique path to it. However, when you reach row>m or col>n, then it’s an invalid path and you should stop traversing. For any grid at row=r and col=c, you have two choices: Traverse to the right or traverse to the bottom. Therefore, the total unique paths at grid (r,c) is equal to the sum of total unique paths from the grid to the right and the grid below. Below is the backtracking code in 5 lines of code:
Method 2 - dynamic programming
In backtracking we will calculate the no of paths for same locations again and again but in Dynamic programming (DP) approach, we can use memoization and will get rid of calculating same locations again and again. For DP soluton just initialize a 2D array(sat paths) of size m x n with all elements as 1. And then apply the formula:
After calculating the entire 2D array, just return paths[m][n].
On a second thought, I see that in place of using a 2D matrix(paths) for memoization, we can just have 1-D array with length as width. Please see the code for the same as below.
Complexity: Since we are traversing each element just once, this solution has linear time complexity.
Method 3 - Treating it as counting problem
Our argument is based on three observations:
Instantiating n with 20, we get the answer to the initial problem of the grid.
References - 1,2
There is an m x n grid. One can only move either down or right at any point in time. One is trying to reach the bottom-right corner of the grid.
How many possible unique paths are there?
(project euler problem 15)
The similar question has been asked in Cracking the coding interview: Here we have to count the unique paths, but there we have to find the unique paths.
Example
Below is an example of 4x4 grid. Here from moving top-left to bottom right corner, we will have 20 unique paths.
1 1 1 1 1 2 3 4 1 3 6 10 1 4 10 20
Solution
Since we know that one can only move either down or right at any point in time so one can reach to cell (i,j) only from 2 possible locations:
- One step right from cell (i-1,j)
- One step down from cell (i,j-1)
- Recursion / Backtracking
- Dynamic programming.
- Treating it as counting problem of Permutation and combination
Method 1 - backtracking
The most direct way is to write code that traverses each possible path, which can be done using backtracking. When you reach row=m and col=n, you know you’ve reached the bottom-right corner, and there is one additional unique path to it. However, when you reach row>m or col>n, then it’s an invalid path and you should stop traversing. For any grid at row=r and col=c, you have two choices: Traverse to the right or traverse to the bottom. Therefore, the total unique paths at grid (r,c) is equal to the sum of total unique paths from the grid to the right and the grid below. Below is the backtracking code in 5 lines of code:
int backtrack(int r, int c, int m, int n) { if (r == m && c == n) return 1; if (r > m || c > n) return 0; return backtrack(r+1, c, m, n) + backtrack(r, c+1, m, n); }
Method 2 - dynamic programming
In backtracking we will calculate the no of paths for same locations again and again but in Dynamic programming (DP) approach, we can use memoization and will get rid of calculating same locations again and again. For DP soluton just initialize a 2D array(sat paths) of size m x n with all elements as 1. And then apply the formula:
Paths[i][j] = paths[i][j-1] + paths[i-1][j]
int no_of_paths(int width, int height) { //Creating paths int** paths = new int*[height]; for(int i = 0; i < height; ++i) paths[i] = new int[width]; int i,j; //Initializing paths for (i=0 ;i< width; i++) { for (j=0; j< height; j++) paths[i][j] = 1; } //Calculating paths for (i=1 ;i< width; i++) { for (j=1; j< height; j++) { paths[i][j] = paths[i-1][j] + paths[i][j-1]; } } //just for printing/debugging purpose for (i=0 ;i< width; i++) { for (j=0; j< height; j++) { cout << paths[i][j] << " "; } cout << endl; } int res = paths[width-1][height-1]; //Deleting paths for(int i = 0; i < height; ++i) { delete [] paths[i]; } delete [] paths; return res; }
On a second thought, I see that in place of using a 2D matrix(paths) for memoization, we can just have 1-D array with length as width. Please see the code for the same as below.
int no_of_paths(int width, int height) { int i,j; int* no = new int[width]; for (i=0 ;i< width; i++) { no[i] = 1; cout << "1 "; //just for printing/debugging purpose } cout << endl; //just for printing/debugging purpose for (i=1 ;i< height; i++) { cout << no[0] << " "; //just for printing/debugging purpose for (j=1; j< width; j++) { no[j] = no[j]+no[j-1]; cout << no[j] << " "; //just for printing/debugging purpose } cout << endl; //just for printing/debugging purpose } int res = no[width-1]; delete [] no; return res; }
Complexity: Since we are traversing each element just once, this solution has linear time complexity.
Method 3 - Treating it as counting problem
Our argument is based on three observations:
- all the paths have size (the reason is obvious: you have to go right positions and down another positions);
- since we can only go right or down, we can identify every path by a string of Rs and Ds, where a R means going right and a D means going down; as an example, the paths illustrated in the problem statement are (from left to right and from top to bottom): RRDD, RDRD, RDDR, DRRD, DRDR and DDRR;
- the strings mentioned above must contain the same number of Rs and Ds.
How many different strings of size , consisting of Rs and n Ds, are there?
The solution is now very simple, because the positioning of Ds (or Rs) determines the positioning of the other Rs (or Ds). Hence, the number we are interested in is the number of ways in which we can choose positions from available positions. The answer, using the traditional notation for the binomial coefficient, is:Generalization to grids
The generalization to an grid is also simple. The only difference is that the strings have length . Using the same reasoning as above, the number of paths through an grid is:References - 1,2
0 comments:
Post a Comment