2812. Find the Safest Path in a Grid
Difficulty: Medium | Date: 2026-06-30
Patterns: BFS | Binary Search | Graphs Data Structures: Matrix
Problem
Given an n x n grid where cells are either 0 (empty) or 1 (thief), find the path from (0,0) to (n-1, n-1) that maximizes the “safety factor” - defined as the minimum Manhattan distance from any thief along the path. Return that maximum safety factor.
My Approach
I knew it was a BFS problem with a twist but couldn’t piece it together on my own. After seeing the hints, it clicked: two-phase approach. First, do a multi-source BFS starting from all thief cells simultaneously to compute the safety factor (min distance to any thief) for every cell in the grid. Second, binary search on the answer - the candidate safety value - and for each candidate, do a BFS from start to end using only cells with safety >= candidate to check feasibility.
The binary search bounds are 0 (minimum possible) and ROWS + COLS (maximum possible Manhattan distance in the grid).
Key Insight
The problem decomposes into two separate BFS passes. The first is a global multi-source BFS from all thieves at once to precompute safety factors - this is the same pattern as “distance to nearest 0” problems. The second uses binary search on the answer with a BFS feasibility check, which sidesteps needing to think about Dijkstra or other shortest-path variants.
Solution
from collections import deque
def maximumSafenessFactor(grid):
ROWS, COLS = len(grid), len(grid[0])
DIRS = [(0,1),(0,-1),(1,0),(-1,0)]
# Phase 1: multi-source BFS from all thieves to compute safety factors
safety = [[0] * COLS for _ in range(ROWS)]
q = deque()
for r in range(ROWS):
for c in range(COLS):
if grid[r][c] == 1:
q.append((r, c, 0))
safety[r][c] = 0
else:
safety[r][c] = -1 # unvisited
while q:
r, c, dist = q.popleft()
for dr, dc in DIRS:
nr, nc = r + dr, c + dc
if 0 <= nr < ROWS and 0 <= nc < COLS and safety[nr][nc] == -1:
safety[nr][nc] = dist + 1
q.append((nr, nc, dist + 1))
# Phase 2: binary search on the minimum safety threshold
def canReach(min_safe):
if safety[0][0] < min_safe or safety[ROWS-1][COLS-1] < min_safe:
return False
visited = [[False] * COLS for _ in range(ROWS)]
q = deque([(0, 0)])
visited[0][0] = True
while q:
r, c = q.popleft()
if r == ROWS - 1 and c == COLS - 1:
return True
for dr, dc in DIRS:
nr, nc = r + dr, c + dc
if 0 <= nr < ROWS and 0 <= nc < COLS and not visited[nr][nc] and safety[nr][nc] >= min_safe:
visited[nr][nc] = True
q.append((nr, nc))
return False
lo, hi = 0, ROWS + COLS
while lo < hi:
mid = (lo + hi + 1) // 2
if canReach(mid):
lo = mid
else:
hi = mid - 1
return loComplexity
- Time: O(n^2 log n) - O(n^2) for multi-source BFS, O(n^2 log n) for binary search with BFS each iteration
- Space: O(n^2) - safety factor grid and visited arrays
Prerequisites
- 2492. Minimum Score of a Path Between Two Cities - multi-source BFS and graph traversal fundamentals