LeetCode1631最小体力消耗路径-----并查集、迪杰斯特拉

题目表述

你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights ,其中 heights[row][col] 表示格子 (row, col) 的高度。一开始你在最左上角的格子 (0, 0) ,且你希望去最右下角的格子 (rows-1, columns-1) (注意下标从 0 开始编号)。你每次可以往 上,下,左,右 四个方向之一移动,你想要找到耗费 体力 最小的一条路径。

一条路径耗费的 体力值 是路径上相邻格子之间 高度差绝对值 的 最大值 决定的。

请你返回从左上角走到右下角的最小 体力消耗值 。

并查集

题目要求找到从左上角到右下角最小的体力消耗值,一般图的问题很容易想到深度优先搜索和广度优先搜索,此外还可以用并查集判断连通性来决定两节点是否可达,这题可以把每个格子当作一个节点,把相邻格子的高度差绝对值当作边的权重。对边的权重排序,然后重新将题目转化为寻找左上角到右下角的连通,每次取最小权重边进行连接两节点,当左上角到右下角连通时,此时边的权重即为答案。
并查集代码为模板类

class union{
        int count;
        int[] parents;
        public union(int N){
            this.count = N;
            parents = new int[N];
            for(int i = 0; i < N; i++){
                parents[i] = i;
            }
        }
        public void unionNode(int x, int y){
            int root1 = find(x);
            int root2 = find(y);
            if(root1 != root2){
                parents[root2] = root1;
            }
        }
        public int find(int node){
            while(parents[node] != node){
                parents[node] = parents[parents[node]];
                node = parents[node];
            }
            return node;
        }
        public boolean isConnected(int node1, int node2){
            return find(node1) == find(node2);
        }
    }
    public int minimumEffortPath(int[][] heights) {
        List<int[]> edges = new ArrayList<>();
        for (int i = 0; i < heights.length; i++) {
            for (int j = 0; j < heights[0].length; j++) {
                if(i+1 < heights.length){
                    edges.add(new int[]{Math.abs(heights[i][j] - heights[i+1][j]), i*heights[0].length + j, (i+1)* heights[0].length + j});
                }
                if(j+1 < heights[0].length){
                    edges.add(new int[]{Math.abs(heights[i][j] - heights[i][j+1]), i*heights[0].length + j, i* heights[0].length + j+1});
                }
            }
        }
        Collections.sort(edges, (a,b)->a[0] - b[0]);
        union un = new union(heights.length * heights[0].length);
        for(int[] edge : edges){
            int weight = edge[0];
            int begin = edge[1];
            int end = edge[2];               
            if(!un.isConnected(begin, end)){
                un.unionNode(begin, end);
            }            
            if(un.isConnected(0,heights.length * heights[0].length - 1)){
                return weight;
            }
        }
        return 0;
    }
posted @ 2022-04-12 14:22  YoungerWb  阅读(87)  评论(0编辑  收藏  举报