【Leetcode】305. Number of Islands II

題目地址:

https://leetcode.com/problems/number-of-islands-ii/

給定一個二維零矩陣,再給點一個數組,數組每個位置是個長爲22的整數數組,是矩陣裏的一個座標。遍歷數組的同時,會把矩陣相應座標位置上的00變爲11。要求在線計算遍歷數組的時候連通塊(島嶼)的數量。

思路是並查集。在遍歷數組的時候,取出座標,如果矩陣在該位置已經有島嶼則略過(這裏主要是預防數組裏有重複座標,也就是同一個位置變了兩次11);如果沒有島嶼,則先將島嶼數加11,然後將這個島嶼和四周的島嶼全做一遍union,每union一次就要將島嶼數減去11,同時動態將島嶼數加入最後答案即可。代碼如下:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Solution {
    
    class UnionFind {
        
        private int[] parent, rank;
        private int count;
        
        public UnionFind(int size) {
            parent = new int[size];
            rank = new int[size];
            // 先標記爲-1,表示這個位置沒有陸地
            Arrays.fill(parent, -1);
            Arrays.fill(rank, 1);
        }
        
        public int find(int p) {
            if (p != parent[p]) {
                parent[p] = find(parent[p]);
            }
            
            return parent[p];
        }
        
        public void union(int p, int q) {
        	// 如果有一個不是陸地,則不用union
            if (parent[p] == -1 || parent[q] == -1) {
                return;
            }
            
            int pRoot = find(p), qRoot = find(q);
            if (pRoot == qRoot) {
                return;
            }
            
            if (rank[pRoot] < rank[qRoot]) {
                parent[pRoot] = qRoot;
            } else if (rank[pRoot] > rank[qRoot]) {
                parent[qRoot] = pRoot;
            } else {
                parent[pRoot] = qRoot;
                rank[qRoot]++;
            }
            // 每union一次,就要將島嶼數量減去1
            count--;
        }
        
        public int getCount() {
            return count;
        }
        
        private void add(int x, int y, int m, int n) {
            int pos = mapToInt(x, y, n);
            // 已經是陸地了,就不用重複變爲陸地了
            if (parent[pos] != -1) {
                return;
            }
            // 先變爲陸地
            parent[pos] = pos;
            // 先假設這個陸地構成了一個新的連通塊,將島嶼數加1,後面union的時候再減
            count++;
            // 四個方向上做union
            if (x + 1 < m) {
                union(mapToInt(x, y, n), mapToInt(x + 1, y, n));
            }
            if (x - 1 >= 0) {
                union(mapToInt(x, y, n), mapToInt(x - 1, y, n));
            }
            if (y + 1 < n) {
                union(mapToInt(x, y, n), mapToInt(x, y + 1, n));
            }
            if (y - 1 >= 0) {
                union(mapToInt(x, y, n), mapToInt(x, y - 1, n));
            }
        }
    
        private int mapToInt(int x, int y, int n) {
            return x * n + y;
        }
    }
    
    public List<Integer> numIslands2(int m, int n, int[][] positions) {
        List<Integer> res = new ArrayList<>();
        UnionFind uf = new UnionFind(m * n);
        for (int i = 0; i < positions.length; i++) {
            int x = positions[i][0], y = positions[i][1];
            uf.add(x, y, m, n);
            res.add(uf.getCount());
        }
        
        return res;
    }
}

時間複雜度O(mnlog(mn))O(mn\log ^*(mn))log\log^*是iterative logarithm),空間複雜度O(mn)O(mn)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章