#2812
Medium Algorithms Find the safest path in a grid
Array Binary Search Breadth-First Search Union-Find Heap (Priority Queue) Matrix
48.6% acceptance
Feb 25, 2026
1822
323
You are given a 0-indexed 2D matrix grid of size n x n, where (r, c) represents:
A cell containing a thief if grid[r][c] = 1
An empty cell if grid[r][c] = 0
You are initially positioned at cell (0, 0). In one move, you can move to any adjacent cell in the grid, including cells containing thieves.
The safeness factor of a path on the grid is defined as the minimum manhattan distance from any cell in the path to any thief in the grid.
Return the maximum safeness factor of all paths leading to cell (n - 1, n - 1).
An adjacent cell of cell (r, c), is one of the cells (r, c + 1), (r, c - 1), (r + 1, c) and (r - 1, c) if it exists.
The Manhattan distance between two cells (a, b) and (x, y) is equal to |a - x| + |b - y|, where |val| denotes the absolute value of val.
Solution
Rust
Time O(n * m)
Space O(n * m)
impl Solution {
pub fn maximum_safeness_factor(grid: Vec<Vec<i32>>) -> i32 {
use std::collections::VecDeque;
let n = grid.len();
let mut dist = vec![vec![i32::MAX; n]; n];
let mut queue: VecDeque<(usize, usize)> = VecDeque::new();
for i in 0..n {
for j in 0..n {
if grid[i][j] == 1 { dist[i][j] = 0; queue.push_back((i, j)); }
}
}
let dirs: [(i32, i32); 4] = [(0,1),(0,-1),(1,0),(-1,0)];
while let Some((r, c)) = queue.pop_front() {
for (dr, dc) in dirs {
let nr = r as i32 + dr; let nc = c as i32 + dc;
if nr >= 0 && nr < n as i32 && nc >= 0 && nc < n as i32 {
let (nr, nc) = (nr as usize, nc as usize);
if dist[nr][nc] == i32::MAX { dist[nr][nc] = dist[r][c] + 1; queue.push_back((nr, nc)); }
}
}
}
let can_reach = |min_d: i32| -> bool {
if dist[0][0] < min_d || dist[n-1][n-1] < min_d { return false; }
let mut visited = vec![vec![false; n]; n];
let mut q: VecDeque<(usize, usize)> = VecDeque::new();
q.push_back((0, 0)); visited[0][0] = true;
while let Some((r, c)) = q.pop_front() {
if r == n-1 && c == n-1 { return true; }
for (dr, dc) in dirs {
let nr = r as i32 + dr; let nc = c as i32 + dc;
if nr >= 0 && nr < n as i32 && nc >= 0 && nc < n as i32 {
let (nr, nc) = (nr as usize, nc as usize);
if !visited[nr][nc] && dist[nr][nc] >= min_d { visited[nr][nc] = true; q.push_back((nr, nc)); }
}
}
}
false
};
let mut lo = 0i32; let mut hi = 2 * n as i32;
while lo < hi {
let mid = (lo + hi + 1) / 2;
if can_reach(mid) { lo = mid; } else { hi = mid - 1; }
}
lo
}
}