forked from kamyu104/LeetCode-Solutions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
path-with-maximum-minimum-value.cpp
111 lines (105 loc) · 3.66 KB
/
path-with-maximum-minimum-value.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Time: O(m * n * log(m * n))
// Space: O(m * n)
// binary search + dfs solution
class Solution {
private:
template <typename T>
struct PairHash {
size_t operator()(const pair<T, T>& p) const {
size_t seed = 0;
seed ^= std::hash<T>{}(p.first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
seed ^= std::hash<T>{}(p.second) + 0x9e3779b9 + (seed<<6) + (seed>>2);
return seed;
}
};
public:
int maximumMinimumPath(vector<vector<int>>& A) {
vector<int> vals;
const auto ceil = min(A[0][0], A.back().back());
for (int i = 0; i < A.size(); ++i) {
for (int j = 0; j < A[0].size(); ++j) {
if (A[i][j] <= ceil) {
vals.emplace_back(A[i][j]);
}
}
}
sort(vals.begin(), vals.end());
vals.erase(unique(vals.begin(), vals.end()), vals.end());
int left = 0, right = vals.size() - 1;
while (left <= right) {
const auto& mid = left + (right - left) / 2;
unordered_set<pair<int, int>, PairHash<int>> lookup;
if (!check(A, vals[mid], 0, 0, &lookup)) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return vals[right];
}
private:
bool check(const vector<vector<int>>& A,
int val, int r, int c,
unordered_set<pair<int, int>, PairHash<int>> *lookup) {
static const vector<pair<int, int>> directions = {{0, 1}, {1, 0},
{0, -1}, {-1, 0}};
if (r == A.size() - 1 && c == A[0].size() - 1) {
return true;
}
lookup->emplace(r, c);
for (const auto& d : directions) {
const auto nr = r + d.first;
const auto nc = c + d.second;
if (0 <= nr && nr < A.size() &&
0 <= nc && nc < A[0].size() &&
!lookup->count({nr, nc}) &&
A[nr][nc] >= val &&
check(A, val, nr, nc, lookup)) {
return true;
}
}
return false;
}
};
// Time: O(m * n * log(m * n))
// Space: O(m * n)
// Dijkstra algorithm solution
class Solution2 {
private:
template <typename T>
struct PairHash {
size_t operator()(const pair<T, T>& p) const {
size_t seed = 0;
seed ^= std::hash<T>{}(p.first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
seed ^= std::hash<T>{}(p.second) + 0x9e3779b9 + (seed<<6) + (seed>>2);
return seed;
}
};
public:
int maximumMinimumPath(vector<vector<int>>& A) {
static const vector<pair<int, int>> directions = {{0, 1}, {1, 0},
{0, -1}, {-1, 0}};
using P = tuple<int, int, int>;
priority_queue<P> max_heap;
max_heap.emplace(A[0][0], 0, 0);
unordered_set<pair<int, int>, PairHash<int>> lookup = {{0, 0}};
while (!max_heap.empty()) {
int i, r, c;
tie(i, r, c) = max_heap.top(); max_heap.pop();
if (r == A.size() - 1 && c == A[0].size() - 1) {
return i;
}
for (const auto& d : directions) {
const auto nr = r + d.first;
const auto nc = c + d.second;
if (0 <= nr && nr < A.size() &&
0 <= nc && nc < A[0].size() &&
!lookup.count({nr, nc})) {
max_heap.emplace(min(i, A[nr][nc]), nr, nc);
lookup.emplace(nr, nc);
}
}
}
return -1;
}
};