Leetcode1631. 最小体力消耗路径

1631. 最小体力消耗路径

Difficulty: 中等

你准备参加一场远足活动。给你一个二维 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 。

示例 2:

输入:heights = [[1,2,3],[3,8,4],[5,3,5]]
输出:1
解释:路径 [1,2,3,4,5] 的相邻格子差值绝对值最大为 1 ,比路径 [1,3,5,3,5] 更优。

示例 3:

输入:heights = [[1,2,1,1,1],[1,2,1,2,1],[1,2,1,2,1],[1,2,1,2,1],[1,1,1,2,1]]
输出:0
解释:上图所示路径不需要消耗任何体力。

提示:

  • rows == heights.length
  • columns == heights[i].length
  • 1 <= rows, columns <= 100
  • 1 <= heights[i][j] <= 10<sup>6</sup>

Solution

思路:查找一条路径使该路径代价最小,路径的代价为该路径上最大权的边。首先题目给的是点的信息,需要先将它转化为图,将二维地图的每一个格视为一个点,相邻的格之间有边相连,边权值为两个格的数值差。
一般我们只要深度遍历或广度遍历图结点计算所有路径的代价即可,但图中点一多就很容易超时,因此,我们转化思路,只要找到一条路径使它从起始点到出发点的代价最小就行,那么我们只要从权重最小的边开始找,当该条边加入图中时能使起点到终点连通,那么该边权重,就是所在路径的代价,也就是要找的结果。
所以,使用并查集判断图是否连通。当一条边加入图中后,起点到终点连通,而且该边的权重为图中最大权值,所以它就是要找的答案。

Language: java

​class Solution {
    public int minimumEffortPath(int[][] heights) {
        int l = heights.length;
        int w = heights[0].length;
        int[][] edges = new int[2*l*w-l-w][3];
        int idx = 0;
        for(int i=0; i<l; i++){
            for(int j=0; j<w; j++) {
                if (j > 0) {
                    edges[idx][0] = i*w+j-1;
                    edges[idx][1] = i*w+j;
                    edges[idx++][2] = Math.abs(heights[i][j - 1] - heights[i][j]);
                }
                if (i > 0) {
                    edges[idx][0] = i*w+j-w;
                    edges[idx][1] = i*w+j;
                    edges[idx++][2] = Math.abs(heights[i - 1][j] - heights[i][j]);
                }
            }
        }
        Arrays.sort(edges, Comparator.comparingInt(a -> a[2]));
        UnionFind uf = new UnionFind(l*w);
        int res = 0;
        for(int i=0; i<edges.length; i++){
            uf.merge(edges[i][0], edges[i][1]);
            if(uf.find(0) == uf.find(l*w-1)){
                res = edges[i][2];
                break;
            }
        }
        return res;
    }
    class UnionFind{
        int[] parent;
        public UnionFind(int len){
            parent = new int[len];
            for(int i=0; i<len; i++) parent[i] = i;
        }

        public int find(int x){
            return parent[x] == x ? x : (parent[x] = find(parent[x]));
        }

        public void merge(int x, int y){
            parent[find(y)] = find(x);
        }
    }
}
原文地址:https://www.cnblogs.com/liuyongyu/p/14347763.html