Bird
Raised Fist0
Interview Prepdp-grid-intervalsmediumAmazonGoogle

Unique Paths II (With Obstacles)

Choose your preparation mode4 modes available
📋
Problem

Imagine a robot navigating a grid warehouse floor where some tiles are blocked by crates. How many ways can it reach the destination without hitting obstacles?

Given an m x n grid filled with 0's (empty cells) and 1's (obstacles), find the number of unique paths from the top-left corner (0,0) to the bottom-right corner (m-1,n-1). You can only move either down or right at any point in time. Return 0 if there is no valid path.

1 ≤ m, n ≤ 100grid[i][j] is either 0 or 1The starting and ending cells are always within the grid
Edge cases: Grid with only one cell and no obstacle → output 1Grid with only one cell and obstacle → output 0Obstacle at starting cell → output 0
</>
IDE
def uniquePathsWithObstacles(obstacleGrid: list[list[int]]) -> int:public int uniquePathsWithObstacles(int[][] obstacleGrid)int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid)function uniquePathsWithObstacles(obstacleGrid)
def uniquePathsWithObstacles(obstacleGrid):
    # Write your solution here
    pass
class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        // Write your solution here
        return 0;
    }
}
#include <vector>
using namespace std;

int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
    // Write your solution here
    return 0;
}
function uniquePathsWithObstacles(obstacleGrid) {
    // Write your solution here
}
Coming soon
0/9
Common Bugs to Avoid
Wrong: 1Greedy approach returning a single path count ignoring obstacles blocking other routes.✅ Use full DP to sum all valid paths from top-left to bottom-right, not just one path.
Wrong: 0Incorrectly returning 0 when start or end cell is not checked properly for obstacles.✅ Add explicit checks for obstacleGrid[0][0] and obstacleGrid[m-1][n-1] before DP computation.
Wrong: Non-zero when end cell blockedFailing to check obstacle at destination cell, counting paths that end on obstacle.✅ Return 0 immediately if obstacleGrid[m-1][n-1] == 1.
Wrong: TLEUsing brute force recursion without memoization or DP on large inputs.✅ Implement bottom-up DP with O(m*n) time complexity.
✓
Test Cases
t1_01basic
Input{"obstacleGrid":[[0,0,0],[0,1,0],[0,0,0]]}
Expected2

There are two paths avoiding the obstacle at position (1,1): right->right->down->down and down->down->right->right.

t1_02basic
Input{"obstacleGrid":[[0,1],[0,0]]}
Expected1

Only one path: down then right, since (0,1) is blocked.

t2_01edge
Input{"obstacleGrid":[[0]]}
Expected1

Single cell grid with no obstacle has exactly one path (start is end).

t2_02edge
Input{"obstacleGrid":[[1]]}
Expected0

Single cell grid with obstacle means no valid path.

t2_03edge
Input{"obstacleGrid":[[1,0],[0,0]]}
Expected0

Start cell is blocked, so no paths exist.

t3_01corner
Input{"obstacleGrid":[[0,0,0],[1,1,0],[0,0,0]]}
Expected1

Only one path exists going right->right->down->down avoiding obstacles blocking the middle row start.

t3_02corner
Input{"obstacleGrid":[[0,0,0,0],[0,1,1,0],[0,0,0,0]]}
Expected2

Multiple paths exist avoiding obstacles in middle row; counting all valid paths is required.

t3_03corner
Input{"obstacleGrid":[[0,0,0],[0,1,0],[0,0,1]]}
Expected0

End cell is blocked, so no valid paths exist.

t4_01performance
Input{"obstacleGrid":[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]}
⏱ Performance - must finish in 2000ms

Large 10x100 grid with no obstacles; n=10, m=100, O(m*n) DP must complete within 2s.

Practice

(1/5)
1. You are given a 2D binary matrix filled with 0's and 1's. The task is to find the largest square containing only 1's and return its area. Which algorithmic approach guarantees an optimal solution with polynomial time complexity?
easy
A. Greedy approach that expands squares from each cell until a zero is found
B. Sorting rows and columns to find the largest continuous block of 1's
C. Depth-First Search exploring all possible squares recursively without memoization
D. Dynamic Programming that builds solutions for smaller squares to find larger ones

Solution

  1. Step 1: Understand problem constraints

    The problem requires finding the largest square of 1's, which depends on overlapping subproblems of smaller squares.
  2. Step 2: Recognize DP pattern

    Dynamic Programming efficiently computes maximal squares by using previously computed smaller squares, avoiding redundant checks.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    DP uses subproblem solutions to build larger squares [OK]
Hint: Largest square -> DP using smaller squares [OK]
Common Mistakes:
  • Thinking greedy expansion always works
  • Confusing DFS with DP
  • Assuming sorting helps find squares
2. You are given an n x n integer matrix. You want to find a path from the top row to the bottom row such that you move one step down each time, and at each step you can move to the same column, the column to the left, or the column to the right. The goal is to minimize the sum of the values along this path. Which algorithmic approach guarantees finding the minimum sum efficiently?
easy
A. Greedy algorithm that picks the minimum adjacent value at each step
B. Sorting each row and picking the smallest values independently
C. Depth-first search exploring all paths without memoization
D. Dynamic programming that builds solutions row by row using previous row results

Solution

  1. Step 1: Understand the problem constraints

    The problem requires considering all possible paths moving down and diagonally, which suggests overlapping subproblems and optimal substructure.
  2. Step 2: Identify the suitable algorithm

    Dynamic programming fits because it efficiently computes minimum sums for each cell based on the previous row's results, avoiding redundant calculations.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Greedy and sorting fail to consider future steps; DFS without memoization is exponential [OK]
Hint: DP uses previous row results to build solutions [OK]
Common Mistakes:
  • Thinking greedy or sorting per row suffices
  • Ignoring overlapping subproblems
3. You need to find the number of distinct ways to move from the top-left corner to the bottom-right corner of an m x n grid, moving only down or right at each step. Which algorithmic approach guarantees an efficient and optimal solution for this problem?
easy
A. Pure brute force recursion exploring all possible paths without memoization
B. Greedy algorithm that always moves towards the direction with fewer remaining steps
C. Dynamic Programming that builds solutions from smaller subproblems using a grid-based state representation
D. Divide and conquer by splitting the grid into quadrants and combining results

Solution

  1. Step 1: Understand problem constraints

    The problem requires counting all unique paths with only right and down moves, which naturally forms overlapping subproblems.
  2. Step 2: Identify suitable approach

    Dynamic Programming efficiently solves overlapping subproblems by storing intermediate results, unlike greedy or pure recursion which are either incorrect or inefficient.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    DP uses subproblem reuse -> optimal and efficient [OK]
Hint: Counting paths with overlapping subproblems -> DP [OK]
Common Mistakes:
  • Thinking greedy can find all paths
  • Using pure recursion without memoization
4. What is the time complexity of the space-optimized bottom-up DP solution for the Cheapest Flights Within K Stops problem, given n cities, E flights, and maximum K stops?
medium
A. O(K * E) because each iteration relaxes all edges up to K+1 times
B. O(n^3) due to nested loops over cities and stops
C. O(E * log n) similar to Dijkstra's algorithm
D. O(n * K^2) due to dynamic programming over stops and cities

Solution

  1. Step 1: Identify loops in the algorithm

    The outer loop runs K+1 times, and the inner loop iterates over all E flights to relax edges.
  2. Step 2: Calculate total complexity

    Each iteration processes E edges, so total time is O(K * E). No nested loops over n^2 or log factors appear.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Algorithm iterates over edges K+1 times [OK]
Hint: Outer loop K+1 times, inner loop over E edges [OK]
Common Mistakes:
  • Confusing E with n^2
  • Assuming Dijkstra complexity
  • Counting recursion stack space
5. The following code attempts to solve the Stone Game problem using bottom-up DP. Identify the line containing the subtle bug that causes incorrect results on some inputs.
def stoneGame(piles):
    n = len(piles)
    dp = [[0]*n for _ in range(n)]
    for i in range(n):
        dp[i][i] = piles[i]
    for length in range(2, n+1):
        for i in range(n - length + 1):
            j = i + length - 1
            dp[i][j] = max(piles[i] + dp[i+1][j], piles[j] + dp[i][j-1])
    return dp[0][n-1] > 0
medium
A. Line computing dp[i][j] = max(piles[i] + dp[i+1][j], piles[j] + dp[i][j-1])
B. Line initializing dp[i][i] = piles[i]
C. Line defining the outer loop for length in range(2, n+1)
D. Line returning dp[0][n-1] > 0

Solution

  1. Step 1: Understand dp state meaning

    dp[i][j] should represent the maximum difference in stones the current player can achieve over the opponent.
  2. Step 2: Identify incorrect recurrence

    The buggy line adds piles[i] + dp[i+1][j], which ignores the opponent's optimal response. The correct formula subtracts dp[i+1][j] to account for opponent's best play.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Correct recurrence uses subtraction, not addition [OK]
Hint: DP recurrence must subtract opponent's score [OK]
Common Mistakes:
  • Adding dp values instead of subtracting opponent's score
  • Forgetting base case initialization
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard