1102. Path With Maximum Minimum Value
Previous1101. The Earliest Moment When Everyone Become FriendsNext1135. Connecting Cities With Minimum Cost
Last updated
Was this helpful?
Last updated
Was this helpful?
Was this helpful?
Given a matrix of integers A
with R rows and C columns, find the maximum score of a path starting at [0,0]
and ending at [R-1,C-1]
.
The score of a path is the minimum value in that path. For example, the value of the path 8 → 4 → 5 → 9 is 4.
A path moves some number of times from one visited cell to any neighbouring unvisited cell in one of the 4 cardinal directions (north, east, west, south).
Example 1:
Input: [[5,4,5],[1,2,6],[7,4,6]]
Output: 4
Explanation:
The path with the maximum score is highlighted in yellow.
Example 2:
Input: [[2,2,1,2,2,2],[1,2,2,2,1,2]]
Output: 2
Example 3:
Input: [[3,4,6,3,4],[0,2,1,1,7],[8,8,3,2,7],[3,2,4,9,8],[4,1,2,0,0],[4,6,5,4,3]]
Output: 3
Note:
1 <= R, C <= 100
0 <= A[i][j] <= 10^9
// BFS Dijkstra
int maximumMinimumPath(vector<vector<int>>& A) { // time: O(mn * log(mn)); space: O(mn)
const vector<pair<int, int> > dirs({ {-1, 0}, {1, 0}, {0, -1}, {0, 1} });
priority_queue<tuple<int, int, int> > pq;
pq.emplace(A[0][0], 0, 0);
const int m = A.size(), n = A[0].size();
int res = A[0][0];
A[0][0] = -1; // mark as visited
while (!pq.empty()) {
auto [a, i, j] = pq.top();
pq.pop();
res = min(res, a);
if (i == m - 1 && j == n - 1) return res; // finish the path
for (const auto& dir : dirs) {
int new_i = i + dir.first, new_j = j + dir.second;
if (new_i < 0 || new_i >= m || new_j < 0 || new_j >= n || A[new_i][new_j] < 0) continue;
pq.emplace(A[new_i][new_j], new_i, new_j);
A[new_i][new_j] = -1; // mark as visited
}
}
return -1;
}
// Binary Search + DFS
bool dfs(const vector<vector<int> >& A, vector<vector<bool> >& visited, const vector<pair<int, int> >& dirs, int val, int i, int j) {
const int m = A.size(), n = A[0].size();
if (i == m - 1 && j == n - 1) return true;
visited[i][j] = true;
for (const auto& dir : dirs) {
int new_i = i + dir.first, new_j = j + dir.second;
if (new_i >= 0 && new_i < m && new_j >= 0 && new_j < n &&
!visited[new_i][new_j] && A[new_i][new_j] >= val &&
dfs(A, visited, dirs, val, new_i, new_j)) return true;
}
return false;
}
bool check(const vector<vector<int> >& A, const vector<pair<int, int> >& dirs, int val) {
const int m = A.size(), n = A[0].size();
vector<vector<bool> > visited(m, vector<bool>(n, false));
return dfs(A, visited, dirs, val, 0, 0);
}
int maximumMinimumPath(vector<vector<int>>& A) { // // time: O(mn * log(mn)); space: O(mn)
const vector<pair<int, int> > dirs({ {-1, 0}, {1, 0}, {0, -1}, {0, 1} });
const int m = A.size(), n = A[0].size();
set<int> unique_vals;
int score_ceiling = min(A[0][0], A[m - 1][n - 1]);
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (A[i][j] <= score_ceiling) unique_vals.insert(A[i][j]);
}
}
vector<int> vals(unique_vals.begin(), unique_vals.end()); // sorted unique value array
int l = 0, r = vals.size() - 1, mid = 0;
while (l <= r) {
mid = l + (r - l) / 2;
if (check(A, dirs, vals[mid])) l = mid + 1;
else r = mid - 1;
}
return vals[r];
}
// Union Find
int find(vector<int>& roots, int i) {
return roots[i] == i ? i : roots[i] = find(roots, roots[i]);
}
void uni(vector<int>& roots, int x, int y) {
int r_x = find(roots, x), r_y = find(roots, y);
if (r_x != r_y) roots[r_y] = r_x;
}
int maximumMinimumPath(vector<vector<int>>& A) { // time: O(mn * log(mn)); space: O(mn)
const vector<pair<int, int> > dirs({ {-1, 0}, {1, 0}, {0, -1}, {0, 1} });
const int m = A.size(), n = A[0].size();
vector<bool> visited(m * n, false);
vector<int> roots(m * n);
vector<pair<int, int> > ids(m * n);
// Initialization of roots vector
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
int k = i * n + j;
roots[k] = k;
ids[k] = {i, j};
}
}
// sort in descending order
auto cmp = [&A](const pair<int, int>& id1, const pair<int, int>& id2) {
return A[id1.first][id1.second] > A[id2.first][id2.second];
};
sort(ids.begin(), ids.end(), cmp);
for (const auto& id : ids) {
int i = id.first, j = id.second, k = i * n + j;
visited[k] = true;
for (const auto& dir : dirs) {
int new_i = i + dir.first, new_j = j + dir.second, new_k = new_i * n + new_j;
if (new_i < 0 || new_i >= m || new_j < 0 || new_j >= n || !visited[new_k]) continue;
uni(roots, k, new_k);
if (find(roots, 0) == find(roots, m * n - 1)) return A[i][j];
}
}
return -1;
}