We need to find a path from the top-left corner to the bottom-right corner of a grid. The path can move in all four directions (not just right and down), and can visit each cell at most once. The "score" of a path is the smallest cell value along that path, and we want to maximize this score.
One way to picture the structure: treat each cell value as the width of a corridor. The bottleneck on any route is its narrowest corridor, and the goal is the route whose narrowest corridor is as wide as possible. This is a maximin path problem.
The distinguishing feature is that we are not minimizing or maximizing a sum. We care about the minimum value along the path, and we want the path that makes that minimum as large as possible. That reframes the problem around thresholds rather than shortest paths: "Is there a path where every cell is at least X?"
1 <= m, n <= 100 → Up to 10,000 cells, so an O(m n log(m * n)) solution is comfortably within limits.0 <= grid[i][j] <= 10^9 → Values fit in a 32-bit signed integer (max ~2.1 * 10^9), so int is safe everywhere and no overflow handling is needed. The large range only affects the binary search bounds.Fix a candidate answer X, meaning we claim there is a path on which every cell has value at least X. Verifying that claim is straightforward: delete every cell with value below X, then check whether (0,0) and (m-1,n-1) are still connected with a BFS or DFS.
The problem then reduces to finding the largest X for which a path of cells with value >= X connects start to end. This is a binary search on the answer, with the search space being the range of cell values. The feasibility test is monotonic: if a path exists for threshold X, it also exists for every threshold Y < X, because lowering the threshold only adds cells and never removes one. That monotonicity is what lets binary search converge on the boundary.
min(grid[0][0], grid[m-1][n-1]) since the path must include both endpoints.mid.mid, run BFS from (0,0) using only cells with value >= mid.mid is feasible. Try a larger threshold (search right half).mid is too large. Search left half.This runs a full BFS up to 30 times. The next approach finds the optimal path in a single traversal by processing cells in order of value.
Grow the explored region outward from (0,0), and whenever there is a choice of which cell to expand into next, expand into the unvisited neighbor with the largest value. Reaching a high-valued cell cannot lower the path's minimum, while a low-valued cell might become the bottleneck, so postponing the low values keeps the running minimum as high as possible.
This is a modified Dijkstra's algorithm. Standard Dijkstra's uses a min-heap to always process the closest node next; here a max-heap always processes the highest-value cell next. Instead of tracking shortest distances, we track the maximum achievable minimum value on the path to each cell. The first time the destination (m-1,n-1) is popped, the running minimum on the path that reached it is the answer.
When a cell is popped from the max-heap, every cell still in the heap or not yet discovered has value no greater than the popped cell, by the heap ordering. So the path that reached the popped cell used only cells with value >= that cell's value, and no alternative route to it could have a higher minimum. Applying this to the destination pop gives the maximum possible minimum, which mirrors why Dijkstra's min-heap pop yields a finalized shortest distance.
score to grid[0][0] (the running minimum along the current best path).score = min(score, value of popped cell).score.The log factor here comes from the heap operations. The next approach replaces the heap with a one-time sort and a Union-Find structure that tracks connectivity as cells are added.
This approach builds the grid up instead of searching it. Add cells one at a time in decreasing order of value, starting with the highest. At some point an added cell connects (0,0) to (m-1,n-1) for the first time, and the value of that cell is the answer.
The reason that value is the answer: when cells are added in decreasing order, every cell added so far has value >= the current one. So the moment start and end become connected, the connecting path consists entirely of cells with value >= the current cell's value, and the current cell is the smallest among them. No path could have a higher minimum, since any earlier connection would have been detected at a higher value.
Union-Find (Disjoint Set Union) tracks the connectivity as cells are added. Each added cell is unioned with its already-added neighbors, and after each step we check whether (0,0) and (m-1,n-1) share a component. The first step where they do gives the answer.
added to track which cells have been added so far.