Given a grid grid[][] of size n × m containing values 0 and 1 having the following meanings:
0 represents an open cell through which movement is allowed.
1 represents a blocked cell that cannot be traversed.
Starting from the top-left cell (0, 0), find the total number of distinct paths to reach the bottom-right cell (n - 1, m - 1). From any cell, movement is allowed only in the right and down directions, and a path is valid only if it passes through open cells.
Note: It is guaranteed that the answer fits within a 32-bit integer.
Examples:
Input: grid[][] = {{0, 0, 0},{0, 1, 0},{0, 0, 0}} Output: 2 Explanation: There are two distinct paths from (0, 0) to (2, 2) while avoiding the blocked cell.
Input: grid[][] = {{1, 0, 1}} Output: 0 Explanation: There is no possible path to reach the end.
[Naive Approach] Using Recursion - O(2^(n*m)) Time and O(n+m) Space
The idea is to start from the top-left cell and try all possible ways to reach the bottom-right cell. From any cell, we can move either down or right. We recursively explore both choices and count the number of valid paths. If we reach a blocked cell or go outside the grid, that path is discarded.
Base Cases:
If i == r or j == c: The current position is out of bounds, so there are no paths available. Return 0.
If grid[i][j] == 1: The current cell is an obstacle, so it cannot be used. Return 0.
If i == r-1 and j == c-1: The function has reached the destination, so there is exactly one path. Return 1.
//Driver Code Starts#include<iostream>#include<vector>usingnamespacestd;//Driver Code Ends// Helper function to find unique paths recursivelyintuniPathRec(inti,intj,vector<vector<int>>&grid){intr=grid.size(),c=grid[0].size();// If out of bounds, return 0if(i==r||j==c){return0;}// If cell is an obstacle, return 0if(grid[i][j]==1){return0;}// If reached the bottom-right cell, return 1if(i==r-1&&j==c-1){return1;}// Recur for the cell below and the cell to the rightreturnuniPathRec(i+1,j,grid)+uniPathRec(i,j+1,grid);}// Function to find unique paths with obstaclesintuniquePaths(vector<vector<int>>&grid){returnuniPathRec(0,0,grid);}//Driver Code Startsintmain(){vector<vector<int>>grid={{0,0,0},{0,1,0},{0,0,0}};cout<<uniquePaths(grid);}//Driver Code Ends
Java
//Driver Code StartspublicclassGFG{//Driver Code Ends// Helper function to find unique paths recursivelystaticintuniPathRec(inti,intj,int[][]grid){intr=grid.length,c=grid[0].length;// If out of bounds, return 0if(i==r||j==c){return0;}// If cell is an obstacle, return 0if(grid[i][j]==1){return0;}// If reached the bottom-right cell, return 1if(i==r-1&&j==c-1){return1;}// Recur for the cell below and the cell to the rightreturnuniPathRec(i+1,j,grid)+uniPathRec(i,j+1,grid);}// Function to find unique paths with obstaclesstaticintuniquePaths(int[][]grid){returnuniPathRec(0,0,grid);}//Driver Code Startspublicstaticvoidmain(String[]args){int[][]grid={{0,0,0},{0,1,0},{0,0,0}};System.out.println(uniquePaths(grid));}}//Driver Code Ends
Python
# Helper function to find unique paths recursivelydefuniPathRec(i,j,grid):r,c=len(grid),len(grid[0])# If out of bounds, return 0ifi==rorj==c:return0# If cell is an obstacle, return 0ifgrid[i][j]==1:return0# If reached the bottom-right cell, return 1ifi==r-1andj==c-1:return1# Recur for the cell below and the cell to the rightreturnuniPathRec(i+1,j,grid)+ \
uniPathRec(i,j+1,grid)# Function to find unique paths with obstaclesdefuniquePaths(grid):returnuniPathRec(0,0,grid)#Driver Code Startsif__name__=="__main__":grid=[[0,0,0],[0,1,0],[0,0,0]]print(uniquePaths(grid))#Driver Code Ends
C#
//Driver Code StartsusingSystem;classGFG{//Driver Code Ends// Helper function to find unique paths recursivelystaticintuniPathRec(inti,intj,int[,]grid){intr=grid.GetLength(0);intc=grid.GetLength(1);// If out of bounds, return 0if(i==r||j==c){return0;}// If cell is an obstacle, return 0if(grid[i,j]==1){return0;}// If reached the bottom-right cell, return 1if(i==r-1&&j==c-1){return1;}// Recur for the cell below and the cell to the rightreturnuniPathRec(i+1,j,grid)+uniPathRec(i,j+1,grid);}// Function to find unique paths with obstaclesstaticintuniquePaths(int[,]grid){returnuniPathRec(0,0,grid);}//Driver Code StartsstaticvoidMain(string[]args){int[,]grid={{0,0,0},{0,1,0},{0,0,0}};Console.WriteLine(uniquePaths(grid));}}//Driver Code Ends
JavaScript
// Helper function to find unique paths recursivelyfunctionuniPathRec(i,j,grid){letr=grid.length,c=grid[0].length;// If out of bounds, return 0if(i===r||j===c){return0;}// If cell is an obstacle, return 0if(grid[i][j]===1){return0;}// If reached the bottom-right cell, return 1if(i===r-1&&j===c-1){return1;}// Recur for the cell below and the cell to the rightreturnuniPathRec(i+1,j,grid)+uniPathRec(i,j+1,grid);}// Function to find unique paths with obstaclesfunctionuniquePaths(grid){returnuniPathRec(0,0,grid);}//Driver Code Starts// Driver codeletgrid=[[0,0,0],[0,1,0],[0,0,0]];console.log(uniquePaths(grid));//Driver Code Ends
Output
2
[Better Approach 1] Using Top-Down DP(Memoization) - O(n*m) Time and O(n*m) Space
The recursive solution repeatedly solves the same subproblems.. To avoid this, we use memoization, where the answer for each cell is stored in a DP array. Before computing the number of paths from a cell, we first check if its result is already available in the DP array. If yes, we return the stored value; otherwise, we compute it recursively, store it, and return it. This ensures that each cell is processed only once.
Create a n × m DP array and initialize all cells with -1.
Start recursion from the top-left cell (0, 0).
If the current cell is invalid or blocked, return 0.
If the destination cell is reached, return 1.
If the answer for the current cell is already stored in DP, return it.
Otherwise, recursively compute the paths by moving down and right.
Store the result in DP and return it.
C++
//Driver Code Starts#include<iostream>#include<vector>usingnamespacestd;//Driver Code Ends// Helper function to find unique pathsintuniPathRec(inti,intj,vector<vector<int>>&grid,vector<vector<int>>&dp){intr=grid.size(),c=grid[0].size();// If out of bounds, return 0if(i==r||j==c){return0;}// If cell is an obstacle, return 0if(grid[i][j]==1){return0;}// If reached the bottom-right cell, return 1if(i==r-1&&j==c-1){return1;}// If already computed, return the stored resultif(dp[i][j]!=-1){returndp[i][j];}// Compute and store the resultdp[i][j]=uniPathRec(i+1,j,grid,dp)+uniPathRec(i,j+1,grid,dp);returndp[i][j];}// Function to find unique paths with obstaclesintuniquePaths(vector<vector<int>>&grid){intn=grid.size(),m=grid[0].size();vector<vector<int>>dp(n,vector<int>(m,-1));returnuniPathRec(0,0,grid,dp);}//Driver Code Startsintmain(){vector<vector<int>>grid={{0,0,0},{0,1,0},{0,0,0}};cout<<uniquePaths(grid);return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.Arrays;publicclassGFG{//Driver Code Ends// Helper function to find unique pathsstaticintuniPathRec(inti,intj,int[][]grid,int[][]dp){intr=grid.length,c=grid[0].length;// If out of bounds, return 0if(i==r||j==c){return0;}// If cell is an obstacle, return 0if(grid[i][j]==1){return0;}// If reached the bottom-right cell, return 1if(i==r-1&&j==c-1){return1;}// If already computed, return the stored resultif(dp[i][j]!=-1){returndp[i][j];}// Compute and store the resultdp[i][j]=uniPathRec(i+1,j,grid,dp)+uniPathRec(i,j+1,grid,dp);returndp[i][j];}// Function to find unique paths with obstaclesstaticintuniquePaths(int[][]grid){intn=grid.length,m=grid[0].length;int[][]dp=newint[n][m];for(int[]row:dp)Arrays.fill(row,-1);returnuniPathRec(0,0,grid,dp);}//Driver Code Startspublicstaticvoidmain(String[]args){int[][]grid={{0,0,0},{0,1,0},{0,0,0}};System.out.println(uniquePaths(grid));}}//Driver Code Ends
Python
# Helper function to find unique pathsdefuniPathRec(i,j,grid,dp):r,c=len(grid),len(grid[0])# If out of bounds, return 0ifi==rorj==c:return0# If cell is an obstacle, return 0ifgrid[i][j]==1:return0# If reached the bottom-right cell, return 1ifi==r-1andj==c-1:return1# If already computed, return the stored resultifdp[i][j]!=-1:returndp[i][j]# Compute and store the resultdp[i][j]=uniPathRec(i+1,j,grid,dp)+ \
uniPathRec(i,j+1,grid,dp)returndp[i][j]# Function to find unique paths with obstaclesdefuniquePaths(grid):n,m=len(grid),len(grid[0])dp=[[-1]*mfor_inrange(n)]returnuniPathRec(0,0,grid,dp)#Driver Code Startsif__name__=="__main__":grid=[[0,0,0],[0,1,0],[0,0,0]]print(uniquePaths(grid))#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;classGFG{//Driver Code Ends// Helper function to find unique pathsstaticintuniPathRec(inti,intj,int[,]grid,int[,]dp){intr=grid.GetLength(0),c=grid.GetLength(1);// If out of bounds, return 0if(i==r||j==c){return0;}// If cell is an obstacle, return 0if(grid[i,j]==1){return0;}// If reached the bottom-right cell, return 1if(i==r-1&&j==c-1){return1;}// If already computed, return the stored resultif(dp[i,j]!=-1){returndp[i,j];}// Compute and store the resultdp[i,j]=uniPathRec(i+1,j,grid,dp)+uniPathRec(i,j+1,grid,dp);returndp[i,j];}// Function to find unique paths with obstaclesstaticintuniquePaths(int[,]grid){intn=grid.GetLength(0),m=grid.GetLength(1);int[,]dp=newint[n,m];for(inti=0;i<n;i++){for(intj=0;j<m;j++){dp[i,j]=-1;}}returnuniPathRec(0,0,grid,dp);}//Driver Code StartsstaticvoidMain(){int[,]grid=newint[,]{{0,0,0},{0,1,0},{0,0,0}};Console.WriteLine(uniquePaths(grid));}}//Driver Code Ends
JavaScript
// Helper function to find unique pathsfunctionuniPathRec(i,j,grid,dp){letr=grid.length,c=grid[0].length;// If out of bounds, return 0if(i===r||j===c){return0;}// If cell is an obstacle, return 0if(grid[i][j]===1){return0;}// If reached the bottom-right cell, return 1if(i===r-1&&j===c-1){return1;}// If already computed, return the stored resultif(dp[i][j]!==-1){returndp[i][j];}// Compute and store the resultdp[i][j]=uniPathRec(i+1,j,grid,dp)+uniPathRec(i,j+1,grid,dp);returndp[i][j];}// Function to find unique paths with obstaclesfunctionuniquePaths(grid){letn=grid.length,m=grid[0].length;letdp=Array.from({length:n},()=>Array(m).fill(-1));returnuniPathRec(0,0,grid,dp);}//Driver Code Starts//Driver Codeletgrid=[[0,0,0],[0,1,0],[0,0,0]];console.log(uniquePaths(grid));//Driver Code Ends
Output
2
[Better Approach 2]Using Bottom-Up DP (Tabulation) – O(n*m) Time and O(n*m) Space
Let dp[i][j] represent the number of valid paths from cell (i, j) to the destination. Since we can move only down or right, the number of paths from a cell is the sum of the paths from the cell below and the cell to its right.
The table is filled in an iterative manner from i = n-1 to i = 1 and j = m-1 to j = 1.
The dynamic programming relation is as follows: dp[i][j] = dp[i+1][j] + dp[i][j+1]
C++
//Driver Code Starts#include<iostream>#include<vector>usingnamespacestd;//Driver Code EndsintuniquePaths(vector<vector<int>>&grid){intn=grid.size(),m=grid[0].size();// If starting or ending cell is an obstacle, return 0if(grid[0][0]==1||grid[n-1][m-1]==1){return0;}vector<vector<int>>dp(n,vector<int>(m,0));dp[n-1][m-1]=1;// Fill the bottom rowfor(intj=m-2;j>=0;j--){// As this is an obstacle, no paths will // exist from this cell.if(grid[n-1][j]==1){break;}// Otherwise, a straight path to // n-1, m-1 exists else{dp[n-1][j]=1;}}// Fill the rightmost columnfor(inti=n-2;i>=0;i--){// As this is an obstacle, no paths will // exist from this cell.if(grid[i][m-1]==1){break;}// Otherwise, a straight path to // n-1, m-1 exists else{dp[i][m-1]=1;}}// Fill the inner cells bottom-up and right-leftfor(inti=n-2;i>=0;i--){for(intj=m-2;j>=0;j--){if(grid[i][j]==0){// Number of paths = sum of paths from the // cell below and the cell to the rightdp[i][j]=dp[i+1][j]+dp[i][j+1];}}}returndp[0][0];}//Driver Code Startsintmain(){vector<vector<int>>grid={{0,0,0},{0,1,0},{0,0,0}};cout<<uniquePaths(grid);return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.Arrays;publicclassGFG{//Driver Code EndsstaticintuniquePaths(int[][]grid){intn=grid.length,m=grid[0].length;// If starting or ending cell is an obstacle, return 0if(grid[0][0]==1||grid[n-1][m-1]==1){return0;}int[][]dp=newint[n][m];dp[n-1][m-1]=1;// Fill the bottom rowfor(intj=m-2;j>=0;j--){// As this is an obstacle, no paths will // exist from this cell.if(grid[n-1][j]==1){break;}// Otherwise, a straight path to // n-1, m-1 exists else{dp[n-1][j]=1;}}// Fill the rightmost columnfor(inti=n-2;i>=0;i--){// As this is an obstacle, no paths will // exist from this cell.if(grid[i][m-1]==1){break;}// Otherwise, a straight path to // n-1, m-1 exists else{dp[i][m-1]=1;}}// Fill the inner cells bottom-up and right-leftfor(inti=n-2;i>=0;i--){for(intj=m-2;j>=0;j--){if(grid[i][j]==0){// Number of paths = sum of paths from the // cell below and the cell to the rightdp[i][j]=dp[i+1][j]+dp[i][j+1];}}}returndp[0][0];}//Driver Code Startspublicstaticvoidmain(String[]args){int[][]grid={{0,0,0},{0,1,0},{0,0,0}};System.out.println(uniquePaths(grid));}}//Driver Code Ends
Python
defuniquePaths(grid):n,m=len(grid),len(grid[0])# If starting or ending cell is an obstacle, return 0ifgrid[0][0]==1orgrid[n-1][m-1]==1:return0dp=[[0]*mfor_inrange(n)]dp[n-1][m-1]=1# Fill the bottom rowforjinrange(m-2,-1,-1):# As this is an obstacle, no paths will # exist from this cell.ifgrid[n-1][j]==1:break# Otherwise, a straight path to # n-1, m-1 exists else:dp[n-1][j]=1# Fill the rightmost columnforiinrange(n-2,-1,-1):# As this is an obstacle, no paths will # exist from this cell.ifgrid[i][m-1]==1:break# Otherwise, a straight path to # n-1, m-1 exists else:dp[i][m-1]=1# Fill the inner cells bottom-up and right-leftforiinrange(n-2,-1,-1):forjinrange(m-2,-1,-1):ifgrid[i][j]==0:# Number of paths = sum of paths from the # cell below and the cell to the rightdp[i][j]=dp[i+1][j]+dp[i][j+1]returndp[0][0]//DriverCodeStartsif__name__=="__main__":grid=[[0,0,0],[0,1,0],[0,0,0]]print(uniquePaths(grid))//DriverCodeEnds
C#
//Driver Code StartsusingSystem;classGFG{//Driver Code EndsstaticintuniquePaths(int[,]grid){intn=grid.GetLength(0),m=grid.GetLength(1);// If starting or ending cell is an obstacle, return 0if(grid[0,0]==1||grid[n-1,m-1]==1){return0;}int[,]dp=newint[n,m];dp[n-1,m-1]=1;// Fill the bottom rowfor(intj=m-2;j>=0;j--){// As this is an obstacle, no paths will // exist from this cell.if(grid[n-1,j]==1)break;// Otherwise, a straight path to // n-1, m-1 exists dp[n-1,j]=1;}// Fill the rightmost columnfor(inti=n-2;i>=0;i--){// As this is an obstacle, no paths will // exist from this cell.if(grid[i,m-1]==1)break;// Otherwise, a straight path to // n-1, m-1 exists dp[i,m-1]=1;}// Fill the inner cells bottom-up and right-leftfor(inti=n-2;i>=0;i--){for(intj=m-2;j>=0;j--){if(grid[i,j]==0){// Number of paths = sum of paths from the // cell below and the cell to the rightdp[i,j]=dp[i+1,j]+dp[i,j+1];}}}returndp[0,0];}//Driver Code StartsstaticvoidMain(){int[,]grid=newint[,]{{0,0,0},{0,1,0},{0,0,0}};Console.WriteLine(uniquePaths(grid));}}//Driver Code Ends
JavaScript
functionuniquePaths(grid){letn=grid.length,m=grid[0].length;// If starting or ending cell is an obstacle, return 0if(grid[0][0]===1||grid[n-1][m-1]===1){return0;}letdp=Array.from({length:n},()=>Array(m).fill(0));dp[n-1][m-1]=1;// Fill the bottom rowfor(letj=m-2;j>=0;j--){// As this is an obstacle, no paths will // exist from this cell.if(grid[n-1][j]===1)break;// Otherwise, a straight path to // n-1, m-1 exists dp[n-1][j]=1;}// Fill the rightmost columnfor(leti=n-2;i>=0;i--){// As this is an obstacle, no paths will // exist from this cell.if(grid[i][m-1]===1)break;// Otherwise, a straight path to // n-1, m-1 exists dp[i][m-1]=1;}// Fill the inner cells bottom-up and right-leftfor(leti=n-2;i>=0;i--){for(letj=m-2;j>=0;j--){if(grid[i][j]===0){// Number of paths = sum of paths from the // cell below and the cell to the rightdp[i][j]=dp[i+1][j]+dp[i][j+1];}}}returndp[0][0];}//Driver Code Starts//Driver Codeletgrid=[[0,0,0],[0,1,0],[0,0,0]];console.log(uniquePaths(grid));//Driver Code Ends
Output
2
[Expected Approach] Using Space Optimized DP – O(m*n) Time and O(n) Space
In previous approach of dynamic programming we have derive the relation between states as given below:
dp[i][j] = dp[i+1][j] + dp[i][j+1]
If we observe that for calculating current dp[i][j] state we only need next row dp[i+1][j] and next cells value. There is no need to store all the next states just one next state is used to compute result.
C++
//Driver Code Starts#include<iostream>#include<vector>usingnamespacestd;//Driver Code EndsintuniquePaths(vector<vector<int>>&grid){intn=grid.size(),m=grid[0].size();// If starting or ending cell is an obstacle, return 0if(grid[0][0]==1||grid[n-1][m-1]==1){return0;}vector<int>dp(m,0);dp[m-1]=1;// Fill the bottom row firstfor(intj=m-2;j>=0;j--){// As this is an obstacle, no paths will // exist from this cell.if(grid[n-1][j]==1){dp[j]=0;}// Otherwise, a straight path to // n-1, m-1 exists else{dp[j]=dp[j+1];}}// Process each row from bottom to topfor(inti=n-2;i>=0;i--){// Process the rightmost column of the current rowif(grid[i][m-1]==1){dp[m-1]=0;}// Process each cell from right to leftfor(intj=m-2;j>=0;j--){// If current cell is an obstacle, paths = 0if(grid[i][j]==1){dp[j]=0;}// Otherwise, paths = sum of right and down pathselse{dp[j]=dp[j]+dp[j+1];}}}returndp[0];}//Driver Code Startsintmain(){vector<vector<int>>grid={{0,0,0},{0,1,0},{0,0,0}};cout<<uniquePaths(grid);return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.Arrays;publicclassGFG{//Driver Code EndsstaticintuniquePaths(int[][]grid){intn=grid.length,m=grid[0].length;// If starting or ending cell is an obstacle, return 0if(grid[0][0]==1||grid[n-1][m-1]==1){return0;}int[]dp=newint[m];dp[m-1]=1;// Fill the bottom row firstfor(intj=m-2;j>=0;j--){// As this is an obstacle, no paths will // exist from this cell.if(grid[n-1][j]==1){dp[j]=0;}// Otherwise, a straight path to // n-1, m-1 exists else{dp[j]=dp[j+1];}}// Process each row from bottom to topfor(inti=n-2;i>=0;i--){// Process the rightmost column of the current rowif(grid[i][m-1]==1){dp[m-1]=0;}// Process each cell from right to leftfor(intj=m-2;j>=0;j--){// If current cell is an obstacle, paths = 0if(grid[i][j]==1){dp[j]=0;}// Otherwise, paths = sum of right and down pathselse{dp[j]=dp[j]+dp[j+1];}}}returndp[0];}//Driver Code Startspublicstaticvoidmain(String[]args){int[][]grid={{0,0,0},{0,1,0},{0,0,0}};System.out.println(uniquePaths(grid));}}//Driver Code Ends
Python
defuniquePaths(grid):n=len(grid)m=len(grid[0])# If starting or ending cell is an obstacle, return 0ifgrid[0][0]==1orgrid[n-1][m-1]==1:return0dp=[0]*mdp[m-1]=1# Fill the bottom row firstforjinrange(m-2,-1,-1):# As this is an obstacle, no paths will # exist from this cell.ifgrid[n-1][j]==1:dp[j]=0# Otherwise, a straight path to # n-1, m-1 exists else:dp[j]=dp[j+1]# Process each row from bottom to topforiinrange(n-2,-1,-1):# Process the rightmost column of the current rowifgrid[i][m-1]==1:dp[m-1]=0# Process each cell from right to leftforjinrange(m-2,-1,-1):# If current cell is an obstacle, paths = 0ifgrid[i][j]==1:dp[j]=0# Otherwise, paths = sum of right and down pathselse:dp[j]=dp[j]+dp[j+1]returndp[0]#Driver Code Startsif__name__=="__main__":grid=[[0,0,0],[0,1,0],[0,0,0]]print(uniquePaths(grid))#Driver Code Ends
C#
//Driver Code StartsusingSystem;publicclassGFG{//Driver Code EndspublicstaticintuniquePaths(int[,]grid){intn=grid.GetLength(0),m=grid.GetLength(1);// If starting or ending cell is an obstacle, return 0if(grid[0,0]==1||grid[n-1,m-1]==1){return0;}int[]dp=newint[m];dp[m-1]=1;// Fill the bottom row firstfor(intj=m-2;j>=0;j--){// As this is an obstacle, no paths will // exist from this cell.if(grid[n-1,j]==1){dp[j]=0;}// Otherwise, a straight path to // n-1, m-1 exists else{dp[j]=dp[j+1];}}// Process each row from bottom to topfor(inti=n-2;i>=0;i--){// Process the rightmost column of the current rowif(grid[i,m-1]==1){dp[m-1]=0;}// Process each cell from right to leftfor(intj=m-2;j>=0;j--){// If current cell is an obstacle, paths = 0if(grid[i,j]==1){dp[j]=0;}// Otherwise, paths = sum of right and down pathselse{dp[j]=dp[j]+dp[j+1];}}}returndp[0];}//Driver Code StartspublicstaticvoidMain(){int[,]grid={{0,0,0},{0,1,0},{0,0,0}};Console.WriteLine(uniquePaths(grid));}}//Driver Code Ends
JavaScript
functionuniquePaths(grid){letn=grid.length,m=grid[0].length;// If starting or ending cell is an obstacle, return 0if(grid[0][0]===1||grid[n-1][m-1]===1){return0;}letdp=Array(m).fill(0);dp[m-1]=1;// Fill the bottom row firstfor(letj=m-2;j>=0;j--){// As this is an obstacle, no paths will // exist from this cell.if(grid[n-1][j]===1){dp[j]=0;}// Otherwise, a straight path to // n-1, m-1 exists else{dp[j]=dp[j+1];}}// Process each row from bottom to topfor(leti=n-2;i>=0;i--){// Process the rightmost column of the current rowif(grid[i][m-1]===1){dp[m-1]=0;}// Process each cell from right to leftfor(letj=m-2;j>=0;j--){// If current cell is an obstacle, paths = 0if(grid[i][j]===1){dp[j]=0;}// Otherwise, paths = sum of right and down pathselse{dp[j]=dp[j]+dp[j+1];}}}returndp[0];}//Driver Code Starts//Driver Codeletgrid=[[0,0,0],[0,1,0],[0,0,0]];console.log(uniquePaths(grid));//Driver Code Ends