气死我了 以为是dp或者回溯 没写出来
又是并查集
题目
https://leetcode-cn.com/problems/path-with-minimum-effort/
分析
代码
class Solution {
public int minimumEffortPath(int[][] heights) {
int m = heights.length;
int n = heights[0].length;
List<int[]> edges = new ArrayList<int[]>();
//edge:顶点1的编号,顶点2的编号,边的高度差绝对值
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
int id = i * n + j;
//上面有边
if (i-1>=0) {
edges.add(new int[]{id - n, id, Math.abs(heights[i][j] - heights[i - 1][j])});
}
//左面有边
if (j-1>=0) {
edges.add(new int[]{id - 1, id, Math.abs(heights[i][j] - heights[i][j - 1])});
}
}
}
//按边权值从大到小排序
Collections.sort(edges, new Comparator<int[]>() {
public int compare(int[] edge1, int[] edge2) {
return edge1[2] - edge2[2];
}
});
//建立并查集
UnionFind uf = new UnionFind(m * n);
int ans = 0;
for (int[] edge : edges) {
int x = edge[0], y = edge[1], v = edge[2];
uf.unite(x, y);
if (uf.connected(0, m * n - 1)) {
ans = v;//这条边的边长就是答案,因为之前加入的边都比这条边长小(边已排序)
break;
}
}
return ans;
}
}
// 并查集模板
class UnionFind {
int[] parent;
int[] size;
int n;
// 当前连通分量数目
int setCount;
public UnionFind(int n) {
this.n = n;
this.setCount = n;
this.parent = new int[n];
this.size = new int[n];
Arrays.fill(size, 1);
for (int i = 0; i < n; ++i) {
parent[i] = i;
}
}
public int findset(int x) {
return parent[x] == x ? x : (parent[x] = findset(parent[x]));
}
public boolean unite(int x, int y) {
x = findset(x);
y = findset(y);
if (x == y) {
return false;
}
if (size[x] < size[y]) {
int temp = x;
x = y;
y = temp;
}
parent[y] = x;
size[x] += size[y];
--setCount;
return true;
}
public boolean connected(int x, int y) {
x = findset(x);
y = findset(y);
return x == y;
}
}