leetcode 1584 连接所有点的最小费用

1584 连接所有点的最小费用

给你一个points 数组,表示 2D 平面上的一些点,其中 points[i] = [xi, yi].
连接点 [xi, yi]和点[xj, yj]的费用为它们之间的曼哈顿距离 :|xi-xj|+|yi- yj|,其中|val|表示val 的绝对值。
请你返回将所有点连接的最小总费用。只有任意两点之间有且仅有一条简单路径时,才认为所有点都已连接。
示例 1:
输入:points = [[0,0],[2,2],[3,10],[5,2],[7,0]]

输出:20
解释:

我们可以按照上图所示连接所有点得到最小总费用,总费用为 20 。
注意到任意两个点之间只有唯一一条路径互相到达。

示例 2:
输入:points = [[3,12],[-2,5],[-4,1]]
输出:18

示例 3:
输入:points = [[0,0],[1,1],[1,0],[-1,1]]
输出:4

示例 4:
输入:points = [[-1000000,-1000000],[1000000,1000000]]
输出:4000000

示例 5:
输入:points = [[0,0]]
输出:0

提示:
1 <= points.length <= 1000
-106 <= xi, yi <= 106
所有点 (xi, yi) 两两不同。

package com.example.lettcode.dailyexercises;

import java.util.Arrays;
import java.util.Comparator;

/**
 * @Class MinCostConnectPoints
 * @Description 1584 连接所有点的最小费用

 * @Author
 * @Date 2021/1/19
 **/
public class MinCostConnectPoints {
    private static class Edge {
        int p1;
        int p2;
        int distance;

        public Edge(int p1, int p2, int distance) {
            this.p1 = p1;
            this.p2 = p2;
            this.distance = distance;
        }
    }

    /**
     * 找到target在并查集中对应的root节点
     *
     * @param target
     * @param rec
     * @return
     */
    public static int find(int target, int[] rec) {
        int root = target;
        /**
         * 一层一层向上找到所对应的根节点
         */
        while (root != rec[root]) {
            root = rec[root];
        }
        // 更新并查集
        int cur = target;
        while (cur != rec[cur]) {
            rec[cur] = root;
            cur = rec[cur];
        }
        return root;
    }

    /**
     * 判断两个点的根是否相同,不同则表示没有连接在树内
     *
     * @param p1
     * @param p2
     * @param rec 并查集,对于每个点都记录其对应的root节点
     * @return
     */
    public static boolean union(int p1, int p2, int[] rec) {
        int rootP1 = find(p1, rec);
        int rootP2 = find(p2, rec);

        rec[rootP1] = rootP2;// 两个根节点指向一起
        return rootP1 == rootP2;
    }

    /**
     * 克鲁斯卡尔算法
     *
     * @param points
     * @return
     */
    public static int kruskal(int[][] points) {
        int length = points.length;
        Edge[] edges = new Edge[length * length];

        // 初始化距离数组
        for (int i = 0; i < length; i++) {
            for (int j = 0; j < length; j++) {
                // 计算出两点之间的距离
                int distance = i == j ? Integer.MAX_VALUE : Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1]);
                // 初始化距离数组
                edges[i * length + j] = new Edge(i, j, distance);
            }
        }
        // 根据距离进行排序
        Arrays.sort(edges, new Comparator<Edge>() {
            @Override
            public int compare(Edge o1, Edge o2) {
                return o1.distance - o2.distance;
            }
        });

        // 初始化并查集数组
        int[] rec = new int[length];
        for (int i = 0; i < length; i++) {
            rec[i] = i;
        }
        int count = 0;
        int cost = 0;
        for (int i = 0; i < edges.length && count < length - 1; i++) {
            Edge edge = edges[i];
            int p1 = edge.p1;
            int p2 = edge.p2;
            if (union(p1, p2, rec) == false) {
                ++count;
                cost += edge.distance;
            }
        }
        return cost;
    }

    public static int minCostConnectPoints(int[][] points) {
        return kruskal(points);
    }
}
// 测试用例
public static void main(String[] args) {
	int[][] points = new int[][]{{0, 0}, {2, 2}, {3, 10}, {5, 2}, {7, 0}};
	int ans = minCostConnectPoints(points);
	System.out.println("MinCostConnectPoints demo01 result:" + ans);

	points = new int[][]{{3, 12}, {-2, 5}, {-4, 1}};
	ans = minCostConnectPoints(points);
	System.out.println("MinCostConnectPoints demo02 result:" + ans);

	points = new int[][]{{0, 0}, {1, 1}, {1, 0}, {-1, 1}};
	ans = minCostConnectPoints(points);
	System.out.println("MinCostConnectPoints demo03 result:" + ans);

	points = new int[][]{{-1000000, -1000000}, {1000000, 1000000}};
	ans = minCostConnectPoints(points);
	System.out.println("MinCostConnectPoints demo04 result:" + ans);

	points = new int[][]{{0, 0}};
	ans = minCostConnectPoints(points);
	System.out.println("MinCostConnectPoints demo05 result:" + ans);
}
原文地址:https://www.cnblogs.com/fyusac/p/14298020.html