并查集算法(Union find)第二式:加权quick-union

参考: 《算法》第四版,p144 - p146

以leetcode, 200th : Number of Islands() 为例 (https://leetcode.com/problems/number-of-islands/

对于加权quick-union算法,N个触点,在最坏情况下,find()、union()、isConnected()的成本增长数量级为lgN

package com.odyssey.app.algorithm.base;

/**
 * 并查集算法 - 以lc200,number of islands 为例
 *
 * @author Dingsheng Huang
 * @date 2020/3/29 16:15
 */
class UnionFind {
    /**
     * 连通分量,计数
     */
    private int count;

    /**
     * 连通分量,标识
     */
    private int[] id;

    /**
     * 加权,根节点对应连通分量的大小
     */
    private int[] rank;


    private void init(char[][] grid, int m, int n) {
        for (int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if (grid[i][j] == '1') {
                    count++;
                }
            }
        }
        id = new int[m * n];
        rank = new int[m * n];
        for (int i = 0; i < m * n; i++) {
            id[i] = i;
            rank[i] = 1;
        }
    }

    // 根节点一定是自旋的,即 p = id[p]
    private int find(int p) {
        while (p != id[p]) {
            p = id[p];
        }
        return p;
    }

    private void union(int p, int q) {
        int pRoot = find(p);
        int qRoot = find(q);
        if (pRoot == qRoot) {
            return;
        }
        if (rank[pRoot] > rank[qRoot]) {
            id[qRoot] = pRoot;
            rank[pRoot] += rank[qRoot];
        } else {
            id[pRoot] = qRoot;
            rank[qRoot] += rank[pRoot];
        }
        count--;
    }

    private boolean isConnected(int p, int q) {
        int pRoot = find(p);
        int qRoot = find(q);
        return pRoot == qRoot;
    }
}
发布了205 篇原创文章 · 获赞 27 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/huangdingsheng/article/details/105229164