1. 程式人生 > 其它 >並查集(UnionFind) 系列

並查集(UnionFind) 系列

547.Number of Provinces

Medium

There arencities. Some of them are connected, while some are not. If cityais connected directly with cityb, and citybis connected directly with cityc, then cityais connected indirectly with cityc.

Aprovinceis a group of directly or indirectly connected cities and no other cities outside of the group.

You are given ann x nmatrixisConnectedwhereisConnected[i][j] = 1if theithcity and thejthcity are directly connected, andisConnected[i][j] = 0otherwise.

Returnthe total number ofprovinces.

Example 1:

Input: isConnected = [[1,1,0],[1,1,0],[0,0,1]]
Output: 2

Example 2:

Input: isConnected = [[1,0,0],[0,1,0],[0,0,1]]
Output: 3

Constraints:

  • 1 <= n <= 200
  • n == isConnected.length
  • n == isConnected[i].length
  • isConnected[i][j]is1or0.
  • isConnected[i][i] == 1
  • isConnected[i][j] == isConnected[j][i]

解法1: 並查集

class Solution {
    public int findCircleNum(int[][] isConnected) {
        //1.for loop len elements do unionfind
        UnionFind uf = new
UnionFind(isConnected.length); for(int i=0;i<isConnected.length;i++){ for(int j=0;j<isConnected.length;j++){ if(i!=j && isConnected[i][j]==1) { uf.union(i,j); } } } //2.count the parent[i]=i int count = 0; for(int i=0;i<isConnected.length;i++) if(uf.parent[i]==i) count++; return count; } //UnionFind implementation class UnionFind{ int[] parent; int[] rank; UnionFind(int n){ parent = new int[n]; rank = new int[n]; for(int i=0;i<n;i++) parent[i]=i; } public int findParent(int x){ if(x==parent[x]) return x; parent[x] = findParent(parent[x]); return parent[x]; } public void union( int x,int y ){ int px = findParent(x); int py = findParent(y); if(px==py) return; if(rank[px]>rank[py]) parent[py]=px; else if(rank[px]<rank[py]) parent[px]=py; else{ parent[px]=py; rank[py]++; } } } }

解法二: dfs

class Solution {
    public int findCircleNum(int[][] isConnected) {
        //defind visited
        int len = isConnected.length;
        boolean[] visited = new boolean[len];
        //for loop 0 ~ len-1  recursively find its connections
        int count = 0;
        for(int i=0;i<len;i++){
            if(visited[i]) continue;
            count++;
            dfs(isConnected,i,visited);
        }
        return count;
    }
    private void dfs(int[][] isConnected,int i,boolean[] visited){
        int len = isConnected.length;
        visited[i]=true;
        for(int j=0;j<len;j++){
            if(isConnected[i][j]==1 && !visited[j] ) dfs(isConnected,j,visited);
        }
    }
}
434 · Number of Islands II Algorithms Medium Description

Given a n,m which means the row and column of the 2D matrix and an array of pair A( size k). Originally, the 2D matrix is all 0 which means there is only sea in the matrix. The list pair has k operator and each operator has two integer A[i].x, A[i].y means that you can change the grid matrix[A[i].x][A[i].y] from sea to island. Return how many island are there in the matrix after each operator.You need to return an array of size K.

0 is represented as the sea, 1 is represented as the island. If two 1 is adjacent, we consider them in the same island. We only consider up/down/left/right adjacent.

Example

Example 1:

Input: n = 4, m = 5, A = [[1,1],[0,1],[3,3],[3,4]]
Output: [1,1,2,2]
Explanation:
0.  00000
    00000
    00000
    00000
1.  00000
    01000
    00000
    00000
2.  01000
    01000
    00000
    00000
3.  01000
    01000
    00000
    00010
4.  01000
    01000
    00000
    00011

Example 2:

Input: n = 3, m = 3, A = [[0,0],[0,1],[2,2],[2,1]]
Output: [1,1,2,2]
/**
 * Definition for a point.
 * class Point {
 *     int x;
 *     int y;
 *     Point() { x = 0; y = 0; }
 *     Point(int a, int b) { x = a; y = b; }
 * }
 */

public class Solution {
    /**
     * @param n: An integer
     * @param m: An integer
     * @param operators: an array of point
     * @return: an integer array
     */
    public List<Integer> numIslands2(int m, int n, Point[] operators) {
        List<Integer> result = new ArrayList();
        UnionFind uf = new UnionFind(m*n);
        int count=0;
        int[][] directions = new int[][]{{-1,0},{1,0},{0,-1},{0,1}};
        boolean[][] visited = new boolean[m][n];
        if(operators==null) return result;
        for(Point p:operators){
            //重複元素直接跳過
            if(visited[p.x][p.y]) {//坑點1:重複元素記得跳過
                result.add(count);
                continue;
            }
            count++;
            visited[p.x][p.y]=true;
            for(int[] dir:directions){
                int nx = p.x+dir[0];
                int ny = p.y+dir[1];
                if( nx>=0 && ny>=0 && nx<m && ny<n ){
                    if(visited[nx][ny] && (uf.find(nx*n+ny)!=uf.find(p.x*n+p.y))){//坑點2:這裡的列數是n,不是m, 因此是p.x*n+p.y   ,另外當且僅當相鄰點已經被訪問過並且還沒有連通的情況下才進行連通並count--
                        count--;
                        uf.union(p.x*n+p.y,nx*n+ny);
                    }
                }
            }
            result.add(count);
        }
        return result;
    }
    class UnionFind{
        int[] parent;
        UnionFind(int n){
            parent = new int[n];
            for(int i=0;i<n;i++) parent[i]=i;
        }
        int find(int x){
            if(x==parent[x]) return x;
            parent[x] = find(parent[x]);
            return parent[x];
        }
        void union(int x,int y){
            int px = find(x);
            int py = find(y);
            if(px==py) return;
            parent[px]=py;
        }
    }
}