Skip to content

Commit ce08212

Browse files
committed
feat: add solutions to lc problem: No.1631.Path With Minimum Effort
1 parent 6e55116 commit ce08212

File tree

6 files changed

+503
-4
lines changed

6 files changed

+503
-4
lines changed

solution/1600-1699/1631.Path With Minimum Effort/README.md

Lines changed: 214 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,27 +54,239 @@
5454
<li><code>1 <= heights[i][j] <= 10<sup>6</sup></code></li>
5555
</ul>
5656

57-
5857
## 解法
5958

6059
<!-- 这里可写通用的实现逻辑 -->
6160

61+
并查集。
62+
63+
并查集模板:
64+
65+
模板 1——朴素并查集:
66+
67+
```python
68+
# 初始化,p存储每个点的父节点
69+
p = list(range(n))
70+
71+
# 返回x的祖宗节点
72+
def find(x):
73+
if p[x] != x:
74+
# 路径压缩
75+
p[x] = find(p[x])
76+
return p[x]
77+
78+
# 合并a和b所在的两个集合
79+
p[find(a)] = find(b)
80+
```
81+
82+
模板 2——维护 size 的并查集:
83+
84+
```python
85+
# 初始化,p存储每个点的父节点,size只有当节点是祖宗节点时才有意义,表示祖宗节点所在集合中,点的数量
86+
p = list(range(n))
87+
size = [1] * n
88+
89+
# 返回x的祖宗节点
90+
def find(x):
91+
if p[x] != x:
92+
# 路径压缩
93+
p[x] = find(p[x])
94+
return p[x]
95+
96+
# 合并a和b所在的两个集合
97+
if find(a) != find(b):
98+
size[find(b)] += size[find(a)]
99+
p[find(a)] = find(b)
100+
```
101+
102+
模板 3——维护到祖宗节点距离的并查集:
103+
104+
```python
105+
# 初始化,p存储每个点的父节点,d[x]存储x到p[x]的距离
106+
p = list(range(n))
107+
d = [0] * n
108+
109+
# 返回x的祖宗节点
110+
def find(x):
111+
if p[x] != x:
112+
t = find(p[x])
113+
d[x] += d[p[x]]
114+
p[x] = t
115+
return p[x]
116+
117+
# 合并a和b所在的两个集合
118+
p[find(a)] = find(b)
119+
d[find(a)] = distance
120+
```
121+
122+
对于本题,每个格子当做图的一个节点,把相邻两个格子的高度差绝对值当做边的权重,因此本题是求解从最左上角的节点到最右下角的节点的连通性问题。
123+
124+
先把图中所有边去掉,然后按照边的权重从小到大,逐个把边添加上。如果在某一次添加一条边时,最左上角和最右下角的节点连通了,那么该边的权重就是题目的最小体力消耗值。
125+
62126
<!-- tabs:start -->
63127

64128
### **Python3**
65129

66130
<!-- 这里可写当前语言的特殊实现逻辑 -->
67131

68132
```python
69-
133+
class Solution:
134+
def minimumEffortPath(self, heights: List[List[int]]) -> int:
135+
m, n = len(heights), len(heights[0])
136+
p = list(range(m * n))
137+
138+
def find(x):
139+
if p[x] != x:
140+
p[x] = find(p[x])
141+
return p[x]
142+
143+
e = []
144+
for i in range(m):
145+
for j in range(n):
146+
if i < m - 1:
147+
e.append([abs(heights[i][j] - heights[i + 1][j]), i * n + j, (i + 1) * n + j])
148+
if j < n - 1:
149+
e.append([abs(heights[i][j] - heights[i][j + 1]), i * n + j, i * n + j + 1])
150+
e.sort()
151+
for h, i, j in e:
152+
p[find(i)] = find(j)
153+
if find(0) == find(m * n - 1):
154+
return h
155+
return 0
70156
```
71157

72158
### **Java**
73159

74160
<!-- 这里可写当前语言的特殊实现逻辑 -->
75161

76162
```java
163+
class Solution {
164+
private int[] p;
165+
166+
public int minimumEffortPath(int[][] heights) {
167+
int m = heights.length, n = heights[0].length;
168+
p = new int[m * n];
169+
for (int i = 0; i < p.length; ++i) {
170+
p[i] = i;
171+
}
172+
List<int[]> edges = new ArrayList<>();
173+
for (int i = 0; i < m; ++i) {
174+
for (int j = 0; j < n; ++j) {
175+
if (i < m - 1) {
176+
edges.add(new int[]{Math.abs(heights[i][j] - heights[i + 1][j]), i * n + j, (i + 1) * n + j});
177+
}
178+
if (j < n - 1) {
179+
edges.add(new int[]{Math.abs(heights[i][j] - heights[i][j + 1]), i * n + j, i * n + j + 1});
180+
}
181+
}
182+
}
183+
Collections.sort(edges, Comparator.comparingInt(a -> a[0]));
184+
for (int[] e : edges) {
185+
int i = e[1], j = e[2];
186+
p[find(i)] = find(j);
187+
if (find(0) == find(m * n - 1)) {
188+
return e[0];
189+
}
190+
}
191+
return 0;
192+
}
193+
194+
private int find(int x) {
195+
if (p[x] != x) {
196+
p[x] = find(p[x]);
197+
}
198+
return p[x];
199+
}
200+
}
201+
```
202+
203+
### **C++**
204+
205+
```cpp
206+
class Solution {
207+
public:
208+
vector<int> p;
209+
210+
int minimumEffortPath(vector<vector<int>>& heights) {
211+
int m = heights.size(), n = heights[0].size();
212+
p.resize(m * n);
213+
for (int i = 0; i < p.size(); ++i) p[i] = i;
214+
vector<vector<int>> edges;
215+
for (int i = 0; i < m; ++i)
216+
{
217+
for (int j = 0; j < n; ++j)
218+
{
219+
if (i < m - 1) edges.push_back({abs(heights[i][j] - heights[i + 1][j]), i * n + j, (i + 1) * n + j});
220+
if (j < n - 1) edges.push_back({abs(heights[i][j] - heights[i][j + 1]), i * n + j, i * n + j + 1});
221+
}
222+
}
223+
sort(edges.begin(), edges.end());
224+
for (auto e : edges)
225+
{
226+
int i = e[1], j = e[2];
227+
p[find(i)] = find(j);
228+
if (find(0) == find(m * n - 1)) return e[0];
229+
}
230+
return 0;
231+
}
232+
233+
int find(int x) {
234+
if (p[x] != x) p[x] = find(p[x]);
235+
return p[x];
236+
}
237+
};
238+
```
77239
240+
### **Go**
241+
242+
```go
243+
var p []int
244+
245+
func minimumEffortPath(heights [][]int) int {
246+
m, n := len(heights), len(heights[0])
247+
p = make([]int, m*n)
248+
for i := 0; i < len(p); i++ {
249+
p[i] = i
250+
}
251+
var edges [][]int
252+
for i := 0; i < m; i++ {
253+
for j := 0; j < n; j++ {
254+
if i < m-1 {
255+
s := []int{abs(heights[i][j] - heights[i+1][j]), i*n + j, (i+1)*n + j}
256+
edges = append(edges, s)
257+
}
258+
if j < n-1 {
259+
s := []int{abs(heights[i][j] - heights[i][j+1]), i*n + j, i*n + j + 1}
260+
edges = append(edges, s)
261+
}
262+
}
263+
}
264+
sort.Slice(edges, func(i, j int) bool {
265+
return edges[i][0] < edges[j][0]
266+
})
267+
for _, e := range edges {
268+
i, j := e[1], e[2]
269+
p[find(i)] = find(j)
270+
if find(0) == find(m*n-1) {
271+
return e[0]
272+
}
273+
}
274+
return 0
275+
}
276+
277+
func find(x int) int {
278+
if p[x] != x {
279+
p[x] = find(p[x])
280+
}
281+
return p[x]
282+
}
283+
284+
func abs(x int) int {
285+
if x > 0 {
286+
return x
287+
}
288+
return -x
289+
}
78290
```
79291

80292
### **...**

0 commit comments

Comments
 (0)