Given a matrix of integers A with R rows and C columns, find the largest minimum value of any path from [0, 0] to [R-1, C-1].
A path is a sequence of cells in the matrix such that we can move from one cell to any adjacent cell in the 4 cardinal directions (up, down, left, right). The score of a path is the minimum value in that path.
[8, 4, 5, 9] has a value of 4.Return the largest minimum value of any path from [0, 0] to [R-1, C-1].
Example 1:
Input: A = [[5,4,5],[1,2,6],[7,4,6]]
Output: 4
Explanation:
The path with the maximum minimum value is highlighted in yellow.
Example 2:
Input: A = [[2,2,1,2,2],[1,2,2,2,1],[1,1,1,2,2]]
Output: 2
Example 3:
Input: A = [[3,4,6,3,4],[0,2,1,1,7],[8,8,3,2,7],[4,9,6,1,1],[5,6,5,2,6]]
Output: 3
Constraints:
1 <= R, C <= 500 <= A[i][j] <= 10^9When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force strategy for finding the path with the maximum minimum value involves exploring every possible path through the grid. We determine the smallest value along each of these paths, and then, select the path where that smallest value is the largest.
Here's how the algorithm would work step-by-step:
def find_max_min_path_brute_force(grid):
rows = len(grid)
cols = len(grid[0])
def explore_paths(row_index, col_index, current_path, min_value_so_far):
if row_index >= rows or col_index >= cols:
return -1 # Path is invalid
current_value = grid[row_index][col_index]
new_min_value = min(min_value_so_far, current_value)
if row_index == rows - 1 and col_index == cols - 1:
return new_min_value # Reached the end
# Explore going down
down_value = explore_paths(row_index + 1, col_index, current_path + [(row_index + 1, col_index)], new_min_value)
# Explore going right
right_value = explore_paths(row_index, col_index + 1, current_path + [(row_index, col_index + 1)], new_min_value)
# Return the larger of the two paths.
return max(down_value, right_value)
# The starting value must be considered.
initial_min = grid[0][0]
max_min_value = explore_paths(0, 0, [(0, 0)], initial_min)
return max_min_valueThe best path through a grid prioritizes high values while guaranteeing connectivity. Instead of exploring all possible paths, we start with high minimum-value thresholds, and then progressively lower these threshold values until a valid path from start to finish is discovered using a connected component search. This ensures efficiency by immediately identifying the best possible minimum value that enables a complete path.
Here's how the algorithm would work step-by-step:
def maximum_minimum_path(grid):
rows = len(grid)
cols = len(grid[0])
left, right = -1, -1
start_value = grid[0][0]
end_value = grid[rows - 1][cols - 1]
left = min(start_value, end_value)
right = 1000000000
while left <= right:
mid = (left + right) // 2
visited = [[False] * cols for _ in range(rows)]
def depth_first_search(row, col):
if row < 0 or row >= rows or col < 0 or col >= cols or visited[row][col] or grid[row][col] < mid:
return False
visited[row][col] = True
if row == rows - 1 and col == cols - 1:
return True
# Explore all 4 directions
return (depth_first_search(row + 1, col) or
depth_first_search(row - 1, col) or
depth_first_search(row, col + 1) or
depth_first_search(row, col - 1))
# Check if a path exists with the current minimum value.
if depth_first_search(0, 0):
left = mid + 1 # Try a higher min value.
else:
right = mid - 1 # Lower min value because current is too high.
# The right pointer holds the maximum minimum value found.
return right| Case | How to Handle |
|---|---|
| Empty grid | Return -1 immediately as there is no path. |
| Grid with a single cell | Return the value of that single cell if it's the only cell. |
| Grid with start or end value of negative infinity | The min-value will always be negative infinity so return negative infinity. |
| All cells in the grid have the same value | The maximum minimum value will be that single repeating value. |
| No path exists from start to end | Return -1 as there is no valid path to consider. |
| Integer overflow when calculating minimum values | Ensure the minimum value calculation uses a data type that can handle the range of potential minimum values without overflow. |
| Large grid exceeding memory limits | Consider optimizing memory usage with techniques like iterative deepening A* or streaming graph algorithms if the grid is too large to hold in memory. |
| Grid with negative values | The algorithm should correctly handle and propagate negative values when determining the minimum path value. |