最小生成树算法(Prim, Kruskal)&& 拓扑排序

连接所有点的最小费用

class Solution {
    public int minCostConnectPoints(int[][] points) {

        //prim算法,时间复杂度 n^2

        int res = 0, n = points.length;

        int[][] g = new int[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                g[i][j] = Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1]);
            }
        }

        //点的集合,已经放入集合为true
        boolean[] v = new boolean[n];
        //lowest[i] 表示 点i 到已放入集合的点的最短距离
        int[] lowest = new int[n];

        //先放入 点0
        v[0] = true;
        //未放入点 i 到已放入点的集合的最短距离,这里是[0],[1, n-1]
        for (int i = 1; i < n; i++) {
            lowest[i] = g[0][i];
        }

        //还有n - 1个点没有放入集合
        for (int i = 1; i < n; i++) {
            int min = Integer.MAX_VALUE, index = -1;
            for (int j = 0; j < n; j++) {
                if (v[j]) continue;
                if (min > lowest[j]) {
                    index = j;
                    min = lowest[j];
                }
            }
            res += min;
            v[index] = true;

            //更新lowest
            for (int j = 0; j < n; j++) {
                if (v[j]) continue;
                lowest[j] = Math.min(lowest[j], g[index][j]);
            }
        }

        return res;
    }
}

 

class Solution {
    public int minCostConnectPoints(int[][] points) {

        //Kruskal算法
        int n = points.length, res = 0;

        //优先队列(小到大)
        PriorityQueue<Edge> heap = new PriorityQueue<>((o1, o2) -> o1.dis - o2.dis);
        //并查集找环
        UF uf = new UF(n);

        //按边的大小从小到达放入优先队列
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                int dis = Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1]);
                heap.offer(new Edge(i, j, dis));
            }
        }

        int mark = 0;
        while (!heap.isEmpty()) {
            Edge e = heap.poll();
            if (uf.union(e.x, e.y)){
                res += e.dis;
                mark++;
            }
            if (mark == n - 1) break;
        }

        return res;
    }


    class Edge {
        private int x, y, dis;
        public Edge(int x, int y, int dis) {
            this.x = x;
            this.y = y;
            this.dis = dis;
        }
    }

    //用并查集
    class UF{
        int[] parent;

        public UF(int n) {
            parent = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }
        } 

        private int find(int x) {
            if (x != parent[x]) {
                parent[x] = find(parent[x]);
            }
            return parent[x];
        }

        public boolean union(int a, int b) {
            int rootA = find(a);
            int rootB = find(b);
            //如果a, b在连通,那么加入a, b就会有环
            if (rootA == rootB) return false;
            parent[rootA] = rootB;
            return true;
        }
    }
}

 

拓扑排序

class Solution {
    public int[] findOrder(int numCourses, int[][] prerequisites) {
        int[] res = new int[numCourses];
        int index = 0;
        //构造图
        List<List<Integer>> list = new ArrayList<>();
        for (int i = 0; i < numCourses; i++) {
            list.add(new ArrayList<>());
        }
        //入度
        int[] indgree = new int[numCourses];

        for (int[] arr : prerequisites) {
            indgree[arr[0]]++;
            list.get(arr[1]).add(arr[0]);
        }
        Queue<Integer> queue = new LinkedList<>();
        //先把入度为0,即没有约束的点放入
        for (int i = 0; i < numCourses; i++) {
            if (indgree[i] == 0) {
                queue.add(i);
            }
        }
        while (!queue.isEmpty()) {
            int x = queue.poll();
            res[index++] = x;
            //想象删除这个点,那么这个点指向的点的入度会减一
            for (int a : list.get(x)) {
                if (--indgree[a] == 0) {
                    queue.offer(a);
                }
            }
        }
        return index == numCourses ? res : new int[0];
    }
}

 

posted @ 2021-01-20 16:36  CPJ31415  阅读(156)  评论(0)    收藏  举报