Given two integers m and n representing the number of rows and columns of a grid, respectively, find the number of distinct paths from the top-left cell (0, 0) to the bottom-right cell (m - 1, n - 1). From any cell, you can move only right or down.
Note: The answer is guaranteed to fit within a 32-bit integer.
Input: m = 2, n = 3 Output: 3 Explanation: There are three distinct paths from the top-left cell to the bottom-right cell.
Input: m = 1, n = 4 Output: 1 Explanation: There is only one possible path from the top-left cell to the bottom-right cell.
[Naive Approach] Using Recursion - O(2^(m+n)) Time and O(m+n) Space
The idea is to start from the top-left cell and recursively explore all possible paths to reach the bottom-right cell. From any cell, we can move either down or right. The total number of paths from the current cell is the sum of the paths obtained by making these two moves.
Base Cases:
If i == m - 1 and j == n - 1, we have reached the destination cell, so return 1.
If i >= m or j >= n, the current position is outside the grid, so return 0.
The recurrence relation will be: solve(i, j, m, n) = solve(i + 1, j, m, n) + solve(i, j + 1, m, n)
C++
#include<iostream>usingnamespacestd;intsolve(inti,intj,intm,intn){// Base case - reached bottom-right cellif(i==m-1&&j==n-1)return1;// Out of boundsif(i>=m||j>=n)return0;// Move down or rightreturnsolve(i+1,j,m,n)+solve(i,j+1,m,n);}intnumberOfPaths(intm,intn){returnsolve(0,0,m,n);}intmain(){intm=2,n=3;cout<<numberOfPaths(m,n);return0;}
Java
classGfG{staticintsolve(inti,intj,intm,intn){// Base case - reached bottom-right cellif(i==m-1&&j==n-1)return1;// Out of boundsif(i>=m||j>=n)return0;// Move down or rightreturnsolve(i+1,j,m,n)+solve(i,j+1,m,n);}staticintnumberOfPaths(intm,intn){returnsolve(0,0,m,n);}publicstaticvoidmain(String[]args){intm=2,n=3;System.out.println(numberOfPaths(m,n));}}
Python
defsolve(i,j,m,n):# Base case - reached bottom-right cellifi==m-1andj==n-1:return1# Out of boundsifi>=morj>=n:return0# Move down or rightreturnsolve(i+1,j,m,n)+solve(i,j+1,m,n)defnumberOfPaths(m,n):returnsolve(0,0,m,n)if__name__=="__main__":m,n=2,3print(numberOfPaths(m,n))
C#
usingSystem;classGFG{staticintsolve(inti,intj,intm,intn){// Base case - reached bottom-right cellif(i==m-1&&j==n-1)return1;// Out of boundsif(i>=m||j>=n)return0;// Move down or rightreturnsolve(i+1,j,m,n)+solve(i,j+1,m,n);}staticintnumberOfPaths(intm,intn){returnsolve(0,0,m,n);}staticvoidMain(){intm=2,n=3;Console.WriteLine(numberOfPaths(m,n));}}
JavaScript
functionsolve(i,j,m,n){// Base case - reached bottom-right cellif(i===m-1&&j===n-1)return1;// Out of boundsif(i>=m||j>=n)return0;// Move down or rightreturnsolve(i+1,j,m,n)+solve(i,j+1,m,n);}functionnumberOfPaths(m,n){returnsolve(0,0,m,n);}//Driver Codeletm=2,n=3;console.log(numberOfPaths(m,n));
Output
3
[Better Approach] Using DP - O(m*n) Time and O(n) Space
The above recursive solution has overlapping subproblems and can be optimized using Dynamic Programming.
Since the number of paths to a cell depends only on the cell directly above it and the cell to its left, we do not need to store the entire m × n DP table.
We use a 1D array dp[], where dp[j] stores the number of paths to reach the current cell in the current row. Initially, there is exactly one way to reach every cell in the first row, so the array is initialized with 1s.
Traverse the grid row by row and update the array from left to right:
dp[j] represents the number of paths from the cell above.
dp[j - 1] represents the number of paths from the cell to the left.
The sum of these two values gives the number of paths to the current cell.
The recurrence relation is: dp[j] = dp[j] + dp[j - 1]
C++
#include<iostream>usingnamespacestd;intnumberOfPaths(intm,intn){// dp[j] stores paths to current cell in the rowintdp[n]={1};// Only one way to reach first columndp[0]=1;for(inti=0;i<m;i++){for(intj=1;j<n;j++){// Paths from top (dp[j]) + left (dp[j-1])dp[j]+=dp[j-1];}}// Paths to bottom-right cellreturndp[n-1];}intmain(){intres=numberOfPaths(2,3);cout<<res<<endl;}
Java
classGFG{staticintnumberOfPaths(intm,intn){// dp[j] stores paths to current cell in the rowint[]dp=newint[n];// Only one way to reach first columndp[0]=1;for(inti=0;i<m;i++){for(intj=1;j<n;j++){// Paths from top (dp[j]) + left (dp[j-1])dp[j]+=dp[j-1];}}// Paths to bottom-right cellreturndp[n-1];}publicstaticvoidmain(String[]args){intres=numberOfPaths(2,3);System.out.println(res);}}
Python
defnumberOfPaths(m,n):# dp[j] stores paths to current cell in the rowdp=[0]*n# Only one way to reach first columndp[0]=1foriinrange(m):forjinrange(1,n):# Paths from top (dp[j]) + left (dp[j-1])dp[j]+=dp[j-1]# Paths to bottom-right cellreturndp[n-1]if__name__=="__main__":res=numberOfPaths(2,3)print(res)
C#
usingSystem;classGFG{staticintnumberOfPaths(intm,intn){// dp[j] stores paths to current cell in the rowint[]dp=newint[n];// Only one way to reach first columndp[0]=1;for(inti=0;i<m;i++){for(intj=1;j<n;j++){// Paths from top (dp[j]) + left (dp[j-1])dp[j]+=dp[j-1];}}// Paths to bottom-right cellreturndp[n-1];}staticvoidMain(){intres=numberOfPaths(2,3);Console.WriteLine(res);}}
JavaScript
functionnumberOfPaths(m,n){// dp[j] stores paths to current cell in the rowletdp=newArray(n).fill(0);// Only one way to reach first columndp[0]=1;for(leti=0;i<m;i++){for(letj=1;j<n;j++){// Paths from top (dp[j]) + left (dp[j-1])dp[j]+=dp[j-1];}}// Paths to bottom-right cellreturndp[n-1];}letres=numberOfPaths(2,3);console.log(res);
Output
3
[Expected Approach] Using Combinatorics - O(min(m, n)) Time and O(1) Space
Instead of computing paths for every cell, we can directly count the number of valid paths using combinatorics. Every path from the top-left cell to the bottom-right cell consists of a fixed number of right and down moves.
To reach cell (m-1, n-1) from (0, 0):
We must make exactly (m - 1) down moves.
We must make exactly (n - 1) right moves.
Therefore, the total number of moves is: (m - 1) + (n - 1) = m + n - 2 .
Each unique path corresponds to a unique arrangement of these moves. So, the problem reduces to choosing positions for either:
(m - 1) down moves among (m + n - 2) total moves, or
(n - 1) right moves among (m + n - 2) total moves.
Hence, the answer is: C(m + n - 2, m - 1) or equivalently, C(m + n - 2, n - 1)
C++
#include<iostream>usingnamespacestd;intnumberOfPaths(intm,intn){// Stores the total number of unique pathslonglongpaths=1;// Total moves needed to reach the destinationinttotalMoves=m+n-2;// Compute C(totalMoves, r), where r is smaller// because C(n, r) = C(n, n - r)intr=min(m-1,n-1);// Calculate the binomial coefficient iterativelyfor(inti=1;i<=r;i++){paths=paths*(totalMoves-r+i)/i;}return(int)paths;}intmain(){intres=numberOfPaths(2,3);cout<<res<<endl;return0;}
Java
classGFG{publicstaticintnumberOfPaths(intm,intn){// Stores the total number of unique pathslongpaths=1;// Total moves needed to reach the destinationinttotalMoves=m+n-2;// Compute C(totalMoves, r), where r is smaller// because C(n, r) = C(n, n - r)intr=Math.min(m-1,n-1);// Calculate the binomial coefficient iterativelyfor(inti=1;i<=r;i++){paths=paths*(totalMoves-r+i)/i;}return(int)paths;}publicstaticvoidmain(String[]args){intres=numberOfPaths(2,3);System.out.println(res);}}
Python
defnumberOfPaths(m,n):# Stores the total number of unique pathspaths=1# Total moves needed to reach the destinationtotalMoves=m+n-2# Compute C(totalMoves, r), where r is smaller# because C(n, r) = C(n, n - r)r=min(m-1,n-1)# Calculate the binomial coefficient iterativelyforiinrange(1,r+1):paths=paths*(totalMoves-r+i)//ireturnint(paths)if__name__=="__main__":res=numberOfPaths(2,3)print(res)
C#
usingSystem;classGFG{staticintnumberOfPaths(intm,intn){// Stores the total number of unique pathslongpaths=1;// Total moves needed to reach the destinationinttotalMoves=m+n-2;// Compute C(totalMoves, r), where r is smaller// because C(n, r) = C(n, n - r)intr=Math.Min(m-1,n-1);// Calculate the binomial coefficient iterativelyfor(inti=1;i<=r;i++){paths=paths*(totalMoves-r+i)/i;}return(int)paths;}staticvoidMain(){intres=numberOfPaths(2,3);Console.WriteLine(res);}}
JavaScript
functionnumberOfPaths(m,n){// Stores the total number of unique pathsletpaths=1n;// Total moves needed to reach the destinationlettotalMoves=m+n-2;// Compute C(totalMoves, r), where r is smaller// because C(n, r) = C(n, n - r)letr=Math.min(m-1,n-1);// Calculate the binomial coefficient iterativelyfor(leti=1;i<=r;i++){paths=paths*BigInt(totalMoves-r+i)/BigInt(i);}returnNumber(paths);}// Driver codeletres=numberOfPaths(2,3);console.log(res);