union-find 算法

2022-03-30  本文已影响0人  放开那个BUG

1、前言

union-find 为并查集算法,原本的用途是判断图的连通性问题,连通性是指图中的两个节点是否相连。说到这,我们是否能想到用 dfs、bfs 判断连通性问题?其实是可以的,union-find 只是多出来一种解决思路而已。

所以记住一点,基本上能用并查集来做的题,bfs、dfs 都能做。

2、概念

并查集的概念很简单,就是原本大家都是在不同的集合里,然后通过合并,最后合并到一个集合里面,就像不同的帮派合并一样。并查集最基本的功能就是 union(合并)。代码如下:

public class UnionFind {
        private int[] parent;

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

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

        public void union(int x, int y) {
            int xRoot = find(x);
            int yRoot = find(y);
            if (xRoot == yRoot) {
                return;
            }

            parent[xRoot] = yRoot;
        }
    }

我们可以用并查集来做一个岛问题。岛问题用 dfs、bfs 都很好找,并查集也很好做。核心思想:将都是1的地方用并查集合并起来,然后最后并查集中1的数量就是岛屿的数量。

class Solution {
    public int numIslands(char[][] grid){
        if(grid == null || grid.length == 0 || grid[0].length == 0){
            return 0;
        }

        int[][] directions = {{1, 0}, {0, 1}};
        int row = grid.length, column = grid[0].length, space = 0;
        UnionFind unionFind = new UnionFind(row * column);
        for(int i = 0; i < row; i++){
            for(int j = 0; j < column; j++){
                if(grid[i][j] == '0'){
                    space++;
                }else {
                    for (int[] direction : directions) {
                        int newX = i + direction[0];
                        int newY = j + direction[1];
                        if(newX < row && newY < column && grid[newX][newY] == '1'){
                            unionFind.union(i * column + j, newX * column + newY);
                        }
                    }
                }
            }
        }

        return unionFind.count - space;
    }

    class UnionFind{
        private int[] parent;
        private int count;

        public UnionFind(int n){
            this.count = n;
            this.parent = new int[n];
            for(int i = 0; i < n; i++){
                this.parent[i] = i;
            }
        }

        private int find(int x){
            while(x != this.parent[x]){
                this.parent[x] = this.parent[this.parent[x]];
                x = this.parent[x];
            }
            return x;
        }

        public void union(int x, int y){
            int xParent = find(x);
            int yParent = find(y);
            if(xParent == yParent){
                return;
            }
            this.parent[xParent] = yParent;
            this.count--;
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读