Talentd
FleetCode
Make and follow sheets.Sign in

Shortest Path in a Grid with Obstacles Elimination solution and explanation

HardArrayBreadth-First SearchMatrix6 min read46.8% acceptanceUpdated 9 Apr 2026
Shortest Path in a Grid with Obstacles Elimination | Live Coding with Explanation | Leetcode - 1293Algorithms Made Easy · 16:28 · 18K viewsWatch on YouTube
9 more videos on this problem
  1. Shortest Path in a Grid with Obstacles Elimination | Live Coding with Explanation | Leetcode - 1293Algorithms Made Easy · 16:28 · 18K views
  2. Shortest Path in a Grid with Obstacles Elimination | Leetcode 1293 | Live coding session 🔥🔥🔥Coding Decoded · 14:40 · 7K views
  3. Leetcode - Shortest Path in a Grid with Obstacles Elimination (Python)Timothy H Chang · 7:33 · 5K views
  4. LeetCode 1293. Shortest Path in a Grid with Obstacles EliminationHappy Coding · 18:53 · 4K views
  5. Leetcode 1293. Shortest Path in a Grid with Obstacles EliminationAlgorithms Casts · 23:38 · 2K views
  6. Shortest Path in a Grid with Obstacles Elimination | Leetcode 1293 | Google QuestionMike the Coder · 34:56 · 1K views
  7. 1293. Shortest Path in a Grid with Obstacles Elimination || Leetcode || C++Code with Sky · 16:54 · 674 views
  8. Daily Leetcode #943: Oct 30, 2022 - 1293. Shortest Path in a Grid with Obstacles EliminationProgramming Live with Larry · 10:51 · 593 views
  9. Shortest Path in a Grid with Obstacles Elimination | LeetCode 1293 | Python SolutionMad Dev Canvas · 17:10 · 569 views
  10. GOOGLE'S #1 INTERVIEW QUESTION (MARCH 2022) | SHORTEST PATH IN GRID WITH OBSTACLE ELIMINATIONCracking FAANG · 20:07 · 12K views

The problem

You are given an m x n integer matrix grid where each cell is either 0 (empty) or 1 (obstacle). You can move up, down, left, or right from and to an empty cell in one step.

Return the minimum number of steps to walk from the upper left corner (0, 0) to the lower right corner (m - 1, n - 1) given that you can eliminate at most k obstacles. If it is not possible to find such walk return -1.

Example 1:

Input: grid = [[0,0,0],[1,1,0],[0,0,0],[0,1,1],[0,0,0]], k = 1
Output: 6
Explanation: 
The shortest path without eliminating any obstacle is 10.
The shortest path with one obstacle elimination at position (3,2) is 6. Such path is (0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (3,2) -> (4,2).

Example 2:

Input: grid = [[0,1,1],[1,1,1],[1,0,0]], k = 1
Output: -1
Explanation: We need to eliminate at least two obstacles to find such a walk.

Constraints:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 40
  • 1 <= k <= m * n
  • grid[i][j] is either 0 or 1.
  • grid[0][0] == grid[m - 1][n - 1] == 0

Approach overview

Problem Overview: You are given an m x n grid where 0 represents an empty cell and 1 represents an obstacle. Starting from the top‑left cell, reach the bottom‑right cell using the minimum number of steps. You can eliminate up to k obstacles during the path. The challenge is tracking both the grid position and how many obstacle removals remain.

Approach 1: Breadth-First Search with State Tracking (Time: O(m * n * k), Space: O(m * n * k))

This problem is a shortest path search on an unweighted grid, which naturally fits Breadth-First Search. The key twist: reaching the same cell with different remaining obstacle eliminations represents different states. Store each state as (row, col, remaining_k) in the BFS queue. When exploring neighbors, if the next cell is an obstacle, decrement the remaining eliminations. Use a 3D visited structure (or track the maximum remaining eliminations seen for each cell) to avoid revisiting weaker states. BFS guarantees the first time you reach the target is the shortest number of steps.

Approach 2: A* Search Algorithm (Time: O(m * n * k log(m * n)), Space: O(m * n * k))

A* improves the search by prioritizing states closer to the goal. Use the Manhattan distance from the current cell to the destination as the heuristic. Each node stores (steps + heuristic) as the priority while still tracking (row, col, remaining_k). This approach explores fewer states in practice because it pushes the search toward the destination instead of expanding uniformly like BFS. The grid structure from matrix problems works well with this heuristic since movement cost is uniform.

Recommended for interviews: Breadth-First Search with state tracking is the expected solution. Interviewers want to see that you model the state correctly and prevent revisiting dominated states. A* demonstrates deeper algorithm knowledge but is rarely required unless the discussion moves toward search optimization.

Approach 1: Breadth-First Search with State Tracking

This approach utilizes Breadth-First Search (BFS) to explore paths in the grid, while maintaining a state that includes the current position and number of obstacles removed. We can advance through the grid using BFS, and track paths using a queue where each entry consists of a tuple containing the current position, number of steps taken, and the number of obstacles removed. A three-dimensional list keeps track of states visited at any position with a particular obstacle count to avoid unnecessary reprocessing.

from collections import deque

def shortestPath(grid, k):
    m, n = len(grid), len(grid[0])
    directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
    queue = deque([(0, 0, 0, 0)])
    visited = [[[False] * (k + 1) for _ in range(n)] for _ in range(m)]
    visited[0][0][0] = True
    while queue:
        x, y, steps, remaining_k = queue.popleft()
        if x == m - 1 and y == n - 1:
            return steps
        for dx, dy in directions:
            nx, ny = x + dx, y + dy
            if 0 <= nx < m and 0 <= ny < n:
                new_k = remaining_k + grid[nx][ny]
                if new_k <= k and not visited[nx][ny][new_k]:
                    visited[nx][ny][new_k] = True
                    queue.append((nx, ny, steps + 1, new_k))
    return -1
import java.util.LinkedList;
import java.util.Queue;

public class ShortestPath {
    public int shortestPath(int[][] grid, int k) {
        int m = grid.length, n = grid[0].length;
        boolean[][][] visited = new boolean[m][n][k + 1];
        Queue<int[]> queue = new LinkedList<>();
        queue.add(new int[]{0, 0, 0, 0});
        visited[0][0][0] = true;

        int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

        while (!queue.isEmpty()) {
            int[] curr = queue.poll();
            int x = curr[0], y = curr[1], steps = curr[2], obstacles = curr[3];

            if (x == m - 1 && y == n - 1) return steps;

            for (int[] d : directions) {
                int nx = x + d[0], ny = y + d[1];
                if (nx >= 0 && nx < m && ny >= 0 && ny < n) {
                    int newObstacles = obstacles + grid[nx][ny];
                    if (newObstacles <= k && !visited[nx][ny][newObstacles]) {
                        visited[nx][ny][newObstacles] = true;
                        queue.add(new int[]{nx, ny, steps + 1, newObstacles});
                    }
                }
            }
        }
        return -1;
    }
}

In the Python solution, we initiate a queue to perform BFS and a visited array to track visited states. Each state contains the (x, y) position, number of steps taken, and the number of obstacles removed. For each state, we try moving in four directions and push valid states into the queue.

Complexity

The time complexity is O(m * n * k) because we process each cell at most k times (once for each possible count of removed obstacles). The space complexity is also O(m * n * k) due to the visited array used for tracking states.

Try this approach in the editor

Approach 2: A* Search Algorithm

A* Search is an informed search algorithm, which is often used in pathfinding and graph traversal. For this grid problem, we use a priority queue to explore paths, using a heuristic function. The heuristic can be the Manhattan distance to the target minus the remaining k value, incentivizing routes closer to the target with lesser obstacle removals.

import heapq

def shortestPath(grid, k):
    m, n = len(grid), len(grid[0])
    def heuristic(x, y):
        return (m - 1 - x) + (n - 1 - y)

    pq = [(heuristic(0, 0), 0, 0, 0, 0)]
    visited = [[float('inf')] * n for _ in range(m)]
    visited[0][0] = 0

    while pq:
        _, steps, x, y, obstacles = heapq.heappop(pq)
        if x == m - 1 and y == n - 1:
            return steps

        for dx, dy in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
            nx, ny = x + dx, y + dy
            if 0 <= nx < m and 0 <= ny < n:
                new_obstacles = obstacles + grid[nx][ny]
                if new_obstacles < visited[nx][ny] and new_obstacles <= k:
                    visited[nx][ny] = new_obstacles
                    heapq.heappush(pq, (steps + 1 + heuristic(nx, ny), steps + 1, nx, ny, new_obstacles))
    return -1
using System;
using System.Collections.Generic;

public class GridPath {
    public int ShortestPath(int[][] grid, int k) {
        int m = grid.Length, n = grid[0].Length;
        int[][] directions = new int[][] { new int[] {0, 1}, new int[] {1, 0}, new int[] {0, -1}, new int[] {-1, 0} };
        var comparer = Comparer<(int f, int steps, int x, int y, int obstacles)>.Create((a, b) => a.f.CompareTo(b.f));
        SortedSet<(int f, int steps, int x, int y, int obstacles)> pq = new SortedSet<(int, int, int, int, int)>(comparer);
        pq.Add((0 + m - 1 + n - 1, 0, 0, 0, 0));
        int[][] visited = new int[m][];
        for (int i = 0; i < m; ++i) { visited[i] = new int[n]; Array.Fill(visited[i], int.MaxValue); }
        visited[0][0] = 0;

        while (pq.Count > 0) {
            var top = pq.Min;
            pq.Remove(top);
            int steps = top.steps, x = top.x, y = top.y, obstacles = top.obstacles;

            if (x == m - 1 && y == n - 1) return steps;

            foreach (var dir in directions) {
                int nx = x + dir[0], ny = y + dir[1];
                if (nx >= 0 && nx < m && ny >= 0 && ny < n) {
                    int new_obstacles = obstacles + grid[nx][ny];
                    if (new_obstacles < visited[nx][ny] && new_obstacles <= k) {
                        visited[nx][ny] = new_obstacles;
                        pq.Add((steps + 1 + m - 1 - nx + n - 1 - ny, steps + 1, nx, ny, new_obstacles));
                    }
                }
            }
        }
        return -1;
    }
}

Leveraging a priority queue for A* search, this Python solution uses a heuristic to decide which paths to explore first. We prioritize paths by their distance to the target, pushing the states into the queue with both the actual cost (steps traveled) and the estimated cost (heuristic).

Complexity

The time complexity is generally higher than BFS due to the additional computation for the heuristic, but edges are still cut off through pruning. The space complexity remains similar to the previous method because of visited state cache retention.

Try this approach in the editor

Approach 3: Default Approach

class Solution {
public:
    int shortestPath(vector<vector<int>>& grid, int k) {
        int m = grid.size(), n = grid[0].size();
        if (k >= m + n - 3) return m + n - 2;
        queue<vector<int>> q;
        q.push({0, 0, k});
        vector<vector<vector<bool>>> vis(m, vector<vector<bool>>(n, vector<bool>(k + 1)));
        vis[0][0][k] = true;
        int ans = 0;
        vector<int> dirs = {-1, 0, 1, 0, -1};
        while (!q.empty()) {
            ++ans;
            for (int i = q.size(); i > 0; --i) {
                auto p = q.front();
                k = p[2];
                q.pop();
                for (int j = 0; j < 4; ++j) {
                    int x = p[0] + dirs[j], y = p[1] + dirs[j + 1];
                    if (x >= 0 && x < m && y >= 0 && y < n) {
                        if (x == m - 1 && y == n - 1) return ans;
                        if (grid[x][y] == 0 && !vis[x][y][k]) {
                            q.push({x, y, k});
                            vis[x][y][k] = true;
                        } else if (grid[x][y] == 1 && k > 0 && !vis[x][y][k - 1]) {
                            q.push({x, y, k - 1});
                            vis[x][y][k - 1] = true;
                        }
                    }
                }
            }
        }
        return -1;
    }
};
function shortestPath(grid: number[][], k: number): number {
    const m = grid.length;
    const n = grid[0].length;
    if (k >= m + n - 3) {
        return m + n - 2;
    }

    let q: Point[] = [[0, 0, k]];
    const vis = Array.from({ length: m }, () =>
        Array.from({ length: n }, () => Array.from({ length: k + 1 }, () => false)),
    );
    vis[0][0][k] = true;
    const dirs = [0, 1, 0, -1, 0];
    let ans = 0;

    while (q.length) {
        const nextQ: Point[] = [];
        ++ans;

        for (const [i, j, k] of q) {
            for (let d = 0; d < 4; ++d) {
                const [x, y] = [i + dirs[d], j + dirs[d + 1]];
                if (x === m - 1 && y === n - 1) {
                    return ans;
                }
                const v = grid[x]?.[y];
                if (v === 0 && !vis[x][y][k]) {
                    nextQ.push([x, y, k]);
                    vis[x][y][k] = true;
                } else if (v === 1 && k > 0 && !vis[x][y][k - 1]) {
                    nextQ.push([x, y, k - 1]);
                    vis[x][y][k - 1] = true;
                }
            }
        }
        q = nextQ;
    }
    return -1;
}

type Point = [number, number, number];
func shortestPath(grid [][]int, k int) int {
	m, n := len(grid), len(grid[0])
	if k >= m+n-3 {
		return m + n - 2
	}
	q := [][]int{[]int{0, 0, k}}
	vis := make([][][]bool, m)
	for i := range vis {
		vis[i] = make([][]bool, n)
		for j := range vis[i] {
			vis[i][j] = make([]bool, k+1)
		}
	}
	vis[0][0][k] = true
	dirs := []int{-1, 0, 1, 0, -1}
	ans := 0
	for len(q) > 0 {
		ans++
		for i := len(q); i > 0; i-- {
			p := q[0]
			q = q[1:]
			k = p[2]
			for j := 0; j < 4; j++ {
				x, y := p[0]+dirs[j], p[1]+dirs[j+1]
				if x >= 0 && x < m && y >= 0 && y < n {
					if x == m-1 && y == n-1 {
						return ans
					}
					if grid[x][y] == 0 && !vis[x][y][k] {
						q = append(q, []int{x, y, k})
						vis[x][y][k] = true
					} else if grid[x][y] == 1 && k > 0 && !vis[x][y][k-1] {
						q = append(q, []int{x, y, k - 1})
						vis[x][y][k-1] = true
					}
				}
			}
		}
	}
	return -1
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Breadth-First Search with State Tracking

The time complexity is O(m * n * k) because we process each cell at most k times (once for each possible count of removed obstacles). The space complexity is also O(m * n * k) due to the visited array used for tracking states.

A* Search Algorithm

The time complexity is generally higher than BFS due to the additional computation for the heuristic, but edges are still cut off through pruning. The space complexity remains similar to the previous method because of visited state cache retention.

Default Approach–

Complexity analysis

ApproachTimeSpaceWhen to Use
Breadth-First Search with State TrackingO(m * n * k)O(m * n * k)Standard interview solution for shortest path in grids with additional state constraints
A* Search AlgorithmO(m * n * k log(m * n))O(m * n * k)When heuristic guidance can reduce explored states and speed up practical performance

Frequently asked questions

Is Shortest Path in a Grid with Obstacles Elimination easy or hard?

Shortest Path in a Grid with Obstacles Elimination is categorized as Hard. The difficulty comes from modeling the BFS state correctly and avoiding revisiting cells when the remaining obstacle eliminations differ.

Shortest Path in a Grid with Obstacles Elimination Python/Java solution

Python and Java implementations typically use a BFS queue storing (row, col, remaining_k, steps). A visited structure tracks states already explored with equal or greater remaining eliminations. This ensures the algorithm runs within O(m * n * k) time.

How to solve Shortest Path in a Grid with Obstacles Elimination in O(m*n*k)?

Use BFS and treat each state as (row, column, remaining eliminations). When moving into a cell with an obstacle, decrease the remaining eliminations. Maintain a visited structure that tracks the best remaining eliminations seen at each cell to prevent redundant exploration.

What is the best approach for Shortest Path in a Grid with Obstacles Elimination?

Breadth-First Search with state tracking is the most reliable approach. Each BFS state includes the cell position and how many obstacle eliminations remain. This guarantees the shortest path in an unweighted grid while correctly handling revisits when the remaining eliminations differ.

Is Shortest Path in a Grid with Obstacles Elimination asked at Google/Amazon/Meta?

Grid shortest-path problems with constraints appear frequently in interviews at companies like Google, Amazon, and Meta. Variants test BFS fundamentals, state modeling, and pruning techniques when additional resources such as obstacle removals are allowed.

What data structure is used in Shortest Path in a Grid with Obstacles Elimination?

The primary data structure is a queue used for Breadth-First Search. A visited structure (often a 3D array or hash set storing row, column, and remaining eliminations) ensures states are not revisited inefficiently.

What is the time complexity of Shortest Path in a Grid with Obstacles Elimination?

The optimal BFS solution runs in O(m * n * k) time because each grid cell can be visited with up to k different elimination states. The space complexity is also O(m * n * k) due to the queue and visited tracking structure.

Comments

Now write it yourselfClose this page and solve Shortest Path in a Grid with Obstacles Elimination in the editor, without looking.
Practise Shortest Path in a Grid with Obstacles Elimination