Skip to content

Commit b8955f3

Browse files
committed
add post
1 parent f3a0847 commit b8955f3

2 files changed

Lines changed: 259 additions & 0 deletions

File tree

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
---
2+
layout: post
3+
title: "一道算法综合题"
4+
date: 2023-10-25
5+
categories: [技术, 数据结构与算法]
6+
tags:
7+
- leetcode
8+
- 数据结构与算法
9+
- DFS
10+
- BFS
11+
- UnionFind
12+
- Dijkstra
13+
---
14+
15+
## 题目描述
16+
17+
You are a hiker preparing for an upcoming hike. You are given heights, a 2D array of size rows x columns, where heights[row][col] represents the height of cell (row, col). You are situated in the top-left cell, (0, 0), and you hope to travel to the bottom-right cell, (rows-1, columns-1) (i.e., 0-indexed). You can move up, down, left, or right, and you wish to find a route that requires the minimum effort.
18+
19+
A route's effort is the maximum absolute difference in heights between two consecutive cells of the route.
20+
21+
Return the minimum effort required to travel from the top-left cell to the bottom-right cell.
22+
23+
- Example 1:
24+
25+
![ex1](/assets/img/post/post-2023-10-25/ex1.png){: width="972" height="589" .w-50 .normal}
26+
27+
```
28+
Input: heights = [[1,2,2],[3,8,2],[5,3,5]]
29+
Output: 2
30+
Explanation: The route of [1,3,5,3,5] has a maximum absolute difference of 2 in consecutive cells.
31+
This is better than the route of [1,2,2,2,5], where the maximum absolute difference is 3.
32+
```
33+
34+
## Binary Search
35+
`DFS/BFS` 判断给定 `threshold` 是否可行,二分搜索确定最小值。
36+
37+
### BFS
38+
```c++
39+
class Solution {
40+
private:
41+
int m, n;
42+
int dir[4][2] = { {0, 1}, {0, -1}, {1, 0}, {-1, 0} };
43+
44+
public:
45+
int minimumEffortPath(vector<vector<int>>& heights) {
46+
m = heights.size();
47+
n = m > 0 ? heights[0].size() : 0;
48+
int left = 0, right = 10e6;
49+
int res = -1;
50+
while (left <= right) {
51+
int mid = left + (right - left) / 2;
52+
bool reachable = bfs(heights, mid);
53+
if (reachable) {
54+
res = mid;
55+
right = mid - 1;
56+
}else {
57+
left = mid + 1;
58+
}
59+
}
60+
return left;
61+
}
62+
63+
bool bfs(vector<vector<int>> &heights, int limit) {
64+
queue<pair<int, int>> q;
65+
q.push({0, 0});
66+
vector<vector<bool>> vis(m, vector<bool>(n, false));
67+
vis[0][0] = true;
68+
while (!q.empty()) {
69+
int x = q.front().first, y = q.front().second;
70+
q.pop();
71+
if (x == m - 1 && y == n - 1) {
72+
return true;
73+
}
74+
for (int i = 0; i < 4; i++) {
75+
int new_x = x + dir[i][0];
76+
int new_y = y + dir[i][1];
77+
if (new_x >= 0 && new_y >= 0 && new_x < m && new_y < n && !vis[new_x][new_y] && abs(heights[new_x][new_y] - heights[x][y]) <= limit) {
78+
q.push({new_x, new_y});
79+
vis[new_x][new_y] = true;
80+
}
81+
}
82+
}
83+
return false;
84+
}
85+
}
86+
87+
```
88+
89+
### DFS
90+
```c++
91+
class Solution {
92+
private:
93+
int m, n;
94+
int dir[4][2] = { {0, 1}, {0, -1}, {1, 0}, {-1, 0} };
95+
96+
public:
97+
int minimumEffortPath(vector<vector<int>>& heights) {
98+
m = heights.size();
99+
n = m > 0 ? heights[0].size() : 0;
100+
vector<vector<bool>> vis(m, vector<bool>(n, false));
101+
int left = 0, right = 10e6;
102+
while (left < right) {
103+
int mid = left + (right - left) / 2;
104+
for (int i = 0; i < m; i++) {
105+
std::fill(vis[i].begin(), vis[i].end(), false);
106+
}
107+
dfs(heights, 0, 0, mid, vis);
108+
if (vis[m - 1][n - 1]) {
109+
right = mid;
110+
}else {
111+
left = mid + 1;
112+
}
113+
}
114+
return left;
115+
}
116+
117+
void dfs(vector<vector<int>> &heights, int x, int y, int threshold, vector<vector<bool>> &vis) {
118+
if (x < 0 || y < 0 || x >= m || y >= n || vis[x][y]) {
119+
return;
120+
}
121+
vis[x][y] = true;
122+
for (int i = 0; i < 4; i++) {
123+
int new_x = x + dir[i][0];
124+
int new_y = y + dir[i][1];
125+
if (new_x < 0 || new_y < 0 || new_x >= m || new_y >= n || vis[new_x][new_y]) {
126+
continue;
127+
}
128+
if (abs(heights[new_x][new_y] - heights[x][y]) > threshold) {
129+
continue;
130+
}
131+
dfs(heights, new_x, new_y, threshold, vis);
132+
}
133+
}
134+
};
135+
```
136+
137+
## UnionFind
138+
```c++
139+
class UnionFind {
140+
private:
141+
vector<int> pa;
142+
int count;
143+
public:
144+
UnionFind(int n):pa(n), count(n) {
145+
for (int i = 0; i < n; i++) {
146+
pa[i] = i;
147+
}
148+
}
149+
int root(int x) {
150+
return x == pa[x] ? x : pa[x] = root(pa[x]);
151+
}
152+
void uni(int x, int y) {
153+
int px = root(x);
154+
int py = root(y);
155+
if (px != py) {
156+
pa[px] = py;
157+
count--;
158+
}
159+
}
160+
bool connected(int x, int y) {
161+
return root(x) == root(y);
162+
}
163+
};
164+
165+
struct Edge {
166+
int x, y;
167+
int d;
168+
Edge(int _x, int _y, int _d): x(_x), y(_y), d(_d) {};
169+
bool operator < (const Edge &other) const {
170+
return d > other.d;
171+
}
172+
};
173+
174+
class Solution {
175+
public:
176+
int minimumEffortPath(vector<vector<int>>& heights) {
177+
int m = heights.size();
178+
int n = heights[0].size();
179+
priority_queue<Edge> edges;
180+
for (int i = 0; i < m; i++) {
181+
for (int j = 0; j < n; j++) {
182+
int id = i * n + j;
183+
if (i > 0) {
184+
edges.push(Edge(id - n, id, abs(heights[i][j] - heights[i - 1][j])));
185+
}
186+
if (j > 0) {
187+
edges.push(Edge(id - 1, id, abs(heights[i][j] - heights[i][j - 1])));
188+
}
189+
}
190+
}
191+
UnionFind uf(m * n);
192+
int res = 0;
193+
while (!edges.empty()) {
194+
Edge e = edges.top();
195+
edges.pop();
196+
uf.uni(e.x, e.y);
197+
if (uf.connected(0, m * n - 1)) {
198+
res = e.d;
199+
break;
200+
}
201+
}
202+
return res;
203+
}
204+
};
205+
```
206+
207+
## Dijkstra
208+
```c++
209+
struct Node {
210+
int x, y;
211+
int limit;
212+
Node(int _x, int _y, int _limit) : x(_x), y(_y), limit(_limit) {}
213+
bool operator < (const Node &other) const {
214+
return limit > other.limit;
215+
}
216+
};
217+
218+
class Solution {
219+
private:
220+
int dirs[4][2] = { {0, 1}, {0, -1}, {1, 0}, {-1, 0} };
221+
222+
public:
223+
int minimumEffortPath(vector<vector<int>>& heights) {
224+
int m = heights.size(), n = m > 0 ? heights[0].size() : 0;
225+
vector<vector<bool>> vis(m, vector<bool>(n, false));
226+
priority_queue<Node> pq;
227+
pq.emplace(Node(0, 0, 0));
228+
vector<int> dist(m * n, INT_MAX);
229+
dist[0] = 0;
230+
while (!pq.empty()) {
231+
Node node = pq.top();
232+
pq.pop();
233+
int x = node.x, y = node.y, limit = node.limit;
234+
if (vis[x][y]) {
235+
continue;
236+
}
237+
if (x == m - 1 && y == n - 1) {
238+
break;
239+
}
240+
vis[x][y] = true;
241+
for (int i = 0; i < 4; i++) {
242+
int nx = x + dirs[i][0];
243+
int ny = y + dirs[i][1];
244+
if (nx < 0 || ny < 0 || nx >= m || ny >= n) {
245+
continue;
246+
}
247+
int new_limit = max(limit, abs(heights[nx][ny] - heights[x][y]));
248+
if (new_limit >= dist[nx * n + ny]) {
249+
continue;
250+
}
251+
dist[nx * n + ny] = new_limit;
252+
pq.emplace(Node(nx, ny, new_limit));
253+
254+
}
255+
}
256+
return dist.back();
257+
}
258+
};
259+
```
10 KB
Loading

0 commit comments

Comments
 (0)