You are given a 0-indexed 2D matrix grid
of size n x n
, where (r, c)
represents:
grid[r][c] = 1
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.
Example 1:
grid = [[1,0,0],[0,0,0],[0,0,1]]
Output: 0
Explanation: All paths from (0, 0) to (n - 1, n - 1) go through the thieves in cells (0, 0) and (n - 1, n - 1).
Example 2:
grid = [[0,0,1],[0,0,0],[0,0,0]]
Output: 2
Explanation: The path depicted in the picture above has a safeness factor of 2 since:
Constraints:
1 <= grid.length == n <= 400
grid[i].length == n
grid[i][j]
is either 0
or 1
.grid
.Let's break down how to solve this problem. The core idea is to find the maximum safeness factor, which is the minimum Manhattan distance from any cell in the path to the nearest thief. This involves a combination of graph traversal (finding paths) and distance calculation.
1. Naive (Brute Force) Approach
The most straightforward approach would be to:
This is highly inefficient because the number of possible paths can grow exponentially with the size of the grid.
2. Optimal Approach: Binary Search + BFS
Instead of generating all possible paths, we can use binary search to find the maximum possible safeness factor. For a given safeness factor k
, we can use Breadth-First Search (BFS) to check if there exists a path from (0, 0) to (n-1, n-1) such that all cells in the path have a safeness of at least k
.
Here's a detailed breakdown:
Calculate Distance to Nearest Thief:
distance
grid where distance[r][c]
is the distance of cell (r, c) to the nearest thief.Binary Search:
low = 0
and high = 2 * (n - 1)
(maximum possible Manhattan distance).low <= high
:
mid = low + (high - low) // 2
.mid
using BFS (see below).low = mid + 1
(try for a larger safeness factor).high = mid - 1
(try for a smaller safeness factor).BFS to Check Path Existence:
k
:
distance[nr][nc] >= k
.true
(a path with safeness factor k
exists).false
.Code Implementation (Python)
from collections import deque
def maximumSafenessFactor(grid):
n = len(grid)
def bfs_distances():
distances = [[float('inf')] * n for _ in range(n)]
queue = deque()
for r in range(n):
for c in range(n):
if grid[r][c] == 1:
distances[r][c] = 0
queue.append((r, c))
while queue:
r, c = queue.popleft()
for dr, dc in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
nr, nc = r + dr, c + dc
if 0 <= nr < n and 0 <= nc < n and distances[nr][nc] == float('inf'):
distances[nr][nc] = distances[r][c] + 1
queue.append((nr, nc))
return distances
distances = bfs_distances()
def can_reach_destination(safeness):
visited = [[False] * n for _ in range(n)]
queue = deque([(0, 0)])
visited[0][0] = True
while queue:
r, c = queue.popleft()
if r == n - 1 and c == n - 1:
return True
for dr, dc in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
nr, nc = r + dr, c + dc
if 0 <= nr < n and 0 <= nc < n and not visited[nr][nc] and distances[nr][nc] >= safeness:
visited[nr][nc] = True
queue.append((nr, nc))
return False
low, high = 0, 2 * (n - 1)
ans = 0
while low <= high:
mid = low + (high - low) // 2
if can_reach_destination(mid):
ans = mid
low = mid + 1
else:
high = mid - 1
return ans
3. Run-time Analysis
4. Space Usage Analysis
5. Edge Cases
In summary, the optimal solution uses binary search to find the maximum safeness factor, combined with BFS to efficiently check the existence of paths for a given safeness factor. The code calculates the Manhattan distance from each cell to the nearest thief and uses this information within the binary search and BFS. The time complexity is O(n^2 log n) and space complexity is O(n^2).