You are given an m x n
integer array grid
. There is a robot initially located at the top-left corner (i.e., grid[0][0]
). The robot tries to move to the bottom-right corner (i.e., grid[m - 1][n - 1]
). The robot can only move either down or right at any point in time.
An obstacle and space are marked as 1
or 0
respectively in grid
. A path that the robot takes cannot include any square that is an obstacle.
Return the number of possible unique paths that the robot can take to reach the bottom-right corner.
The testcases are generated so that the answer will be less than or equal to 2 * 109
.
Example 1:
Input: obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]] Output: 2 Explanation: There is one obstacle in the middle of the 3x3 grid above. There are two ways to reach the bottom-right corner: 1. Right -> Right -> Down -> Down 2. Down -> Down -> Right -> Right
Example 2:
Input: obstacleGrid = [[0,1],[0,0]] Output: 1
Constraints:
m == obstacleGrid.length
n == obstacleGrid[i].length
1 <= m, n <= 100
obstacleGrid[i][j]
is 0
or 1
.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force method explores every possible route from the starting point to the destination. It's like trying every single path you can think of, one at a time, until you find all the valid routes avoiding obstacles. We will check each route to determine if it is valid.
Here's how the algorithm would work step-by-step:
def unique_paths_ii_brute_force(obstacle_grid):
number_of_rows = len(obstacle_grid)
number_of_columns = len(obstacle_grid[0])
path_count = 0
def traverse_grid(row, column):
nonlocal path_count
# If we are out of bounds or on an obstacle, this is an invalid path
if row < 0 or row >= number_of_rows or column < 0 or column >= number_of_columns or obstacle_grid[row][column] == 1:
return
# We found a valid path to the end
if row == number_of_rows - 1 and column == number_of_columns - 1:
path_count += 1
return
# Explore going down
traverse_grid(row + 1, column)
# Explore going right
traverse_grid(row, column + 1)
# Start traversal at top-left corner
traverse_grid(0, 0)
return path_count
The problem asks us to find how many different routes exist to reach the end point of a grid, given that some spots are blocked. The clever solution involves building up a table of routes from the start, only considering valid paths. This is a dynamic programming approach, which smartly reuses prior calculations.
Here's how the algorithm would work step-by-step:
def uniquePathsWithObstacles(obstacle_grid):
grid_height = len(obstacle_grid)
grid_width = len(obstacle_grid[0])
# If the start or end has an obstacle, there are no paths.
if obstacle_grid[0][0] == 1 or obstacle_grid[grid_height - 1][grid_width - 1] == 1:
return 0
path_counts = [[0] * grid_width for _ in range(grid_height)]
path_counts[0][0] = 1
for row_index in range(grid_height):
for column_index in range(grid_width):
if obstacle_grid[row_index][column_index] == 1:
continue
# Sum paths from above if not on the top row
if row_index > 0:
path_counts[row_index][column_index] += path_counts[row_index - 1][column_index]
# Sum paths from the left if not on the left most column
if column_index > 0:
path_counts[row_index][column_index] += path_counts[row_index][column_index - 1]
return path_counts[grid_height - 1][grid_width - 1]
Case | How to Handle |
---|---|
Null or empty obstacleGrid | Return 0 immediately if the input is null or has zero rows/columns because there are no possible paths. |
Starting cell is an obstacle | Return 0 immediately since no path can start from an obstacle. |
Ending cell is an obstacle | The dynamic programming approach will ensure that the number of paths to the destination cell is 0 if it's an obstacle. |
1x1 grid with no obstacle | Return 1 as there is one path which is to stay at the only cell. |
All cells are obstacles | Return 0 because there are no valid paths when every cell is blocked. |
Obstacle directly blocking the start to end path | The dynamic programming approach will result in 0 paths if the obstacle makes it impossible to reach the destination. |
Integer overflow for very large grids | Use a long integer data type instead of int to store the number of paths to prevent overflow. |
m x 1 or 1 x n grid with an obstacle | If there's an obstacle in the single path, the number of paths becomes 0; otherwise, it's 1. |