一、题目描述
你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights ,其中 heights[row][col] 表示格子 (row, col) 的高度。一开始你在最左上角的格子 (0, 0) ,且你希望去最右下角的格子 (rows-1, columns-1) (注意下标从 0 开始编号)。你每次可以往 上,下,左,右 四个方向之一移动,你想要找到耗费 体力 最小的一条路径。
一条路径耗费的 体力值 是路径上相邻格子之间 高度差绝对值 的 最大值 决定的。
请你返回从左上角走到右下角的最小 体力消耗值 。
示例 1:
输入:heights = [[1,2,2],[3,8,2],[5,3,5]]
输出:2
解释:路径 [1,3,5,3,5] 连续格子的差值绝对值最大为 2 。
这条路径比路径 [1,2,2,2,5] 更优,因为另一条路径差值最大值为 3 。
二、题解
方法一:并查集
class Solution {
public int minimumEffortPath(int[][] heights) {
int rows = heights.length;int cols = heights[0].length;UnionFind uf = new UnionFind(rows * cols);List<int[]> edges = new ArrayList<>();for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
int id = i * cols + j;//当前结点的编号(从0到m*n-1)//每个节点都连接上面和左边的两条边(除边界点)if(i>0)edges.add(new int[]{
id-cols,id,Math.abs(heights[i-1][j]-heights[i][j])});if(j>0)edges.add(new int[]{
id-1,id,Math.abs(heights[i][j-1]-heights[i][j])});}}if(edges.size()==0)return 0;//将边按照权重从小到大排序Collections.sort(edges,new Comparator<int[]>(){
public int compare(int[] a,int[] b){
return a[2] - b[2];}});int edgeIndex=0;//当前归并到的边while(!uf.connect(0,rows * cols-1)){
uf.merge(edges.get(edgeIndex)[0],edges.get(edgeIndex)[1]);edgeIndex++;}return edges.get(edgeIndex-1)[2];}}
//并查集模板
class UnionFind{
private int n;private int count;private int[] parent;private int[] size;public UnionFind(int _n){
this.n = _n;this.count = _n;parent = new int[_n];size = new int[_n];Arrays.fill(size,1);for(int i=0;i<n;i++)parent[i] = i;}public int find(int x){
return x==parent[x]?x:(parent[x]=find(parent[x]));}public boolean merge(int x,int y){
x = find(x);y = find(y);if(x==y) return false;if(size[x]<=size[y])parent[x] = y;elseparent[y] = x;if(size[x]==size[y])size[y]++;--count;return true;}public boolean connect(int x,int y){
x = find(x);y = find(y);if(x == y) return true;else return false;}
}