并查集的优化及应用

2018-05-01 15:13:08

并查集是一个时空复杂度非常优越的数据结构,并且通过优化后其复杂度为<O(1),O(n)>。

并查集的优化主要有两个方面:

  • 路径压缩
  • 按rank来合并

路径压缩:

按rank合并:

public class UnionFindSet {
    private int[] parent;
    private int[] rank;

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

    public int find(int i) {
        if (parent[i] != i)
            parent[i] = find(parent[i]);
        return parent[i];
    }

    public boolean union(int i, int j) {
        int pi = find(i);
        int pj = find(j);

        if (pi == pj) return false;

        if (rank[pi] > rank[pj])
            parent[pj] = pi;
        else if (rank[pi] < rank[pj])
            parent[pi] = pj;
        else {
            parent[pj] = pi;
            rank[pi]++;
        }
        return true;
    }
}
  • 684. Redundant Connection

问题描述:

问题求解:

树形下的无向图判断环路问题,图的描述方式是采用边集。

并查集本身就是树形结构,而树是一个无向图,具体来说,树是一个无环的连通图,所以本题可以直接使用并查集来进行求解。

    public int[] findRedundantConnection(int[][] edges) {
        UnionFindSet ufs = new UnionFindSet(edges.length + 1);
        int[] res = new int[2];
        for (int[] pair : edges) {
            if (!ufs.union(pair[0], pair[1])) {
                res[0] = Math.min(pair[0], pair[1]);
                res[1] = Math.max(pair[0], pair[1]);
                break;
            }
        }
        return res;
    }
  • 547. Friend Circles

问题描述:

问题求解:

class Solution {
    public int findCircleNum(int[][] M) {
        UnionFindSet ufs = new UnionFindSet(M.length);
        int res = 0;
        for (int i = 0; i < M.length; i++) {
            for (int j = 0; j < i; j++) {
                if (M[i][j] == 1)
                    ufs.union(i, j);
            }
        }
        for (int i = 0; i < ufs.parent.length; i++) 
            if (ufs.parent[i] == i) res++;
        return res;
    }
}

class UnionFindSet {
    public int[] parent;
    private int[] rank;

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

    public int find(int i) {
        if (parent[i] != i)
            parent[i] = find(parent[i]);
        return parent[i];
    }

    public boolean union(int i, int j) {
        int pi = find(i);
        int pj = find(j);

        if (pi == pj) return false;

        if (rank[pi] > rank[pj])
            parent[pj] = pi;
        else if (rank[pi] < rank[pj])
            parent[pi] = pj;
        else {
            parent[pj] = pi;
            rank[pi]++;
        }
        return true;
    }
}

猜你喜欢

转载自www.cnblogs.com/TIMHY/p/8976359.html
今日推荐