0095 經典算法系列——並查集(Union-Find)

概念TODO

UF的標準模板

算法實戰

  • 等式方程的可滿足性(medium)
  • 朋友圈(medium)
  • 最長連續序列(hard)

下面將介紹以上題目的實現:
等式方程的可滿足性(medium)
分析

  • List item
class Solution {
    public boolean equationsPossible(String[] equations) {
        int n = equations.length;
        UF uf = new UF();
        
        for (int i = 0; i < n; i++) {
            if (equations[i].charAt(1) == '='){
                uf.union(equations[i].charAt(0) - 'a', equations[i].charAt(3) - 'a');
            }
        }
        
        for (int i = 0; i < n; i++) {
            if (equations[i].charAt(1) == '=' && !uf.connected(equations[i].charAt(0) - 'a', equations[i].charAt(3) - 'a') ){
               return false;         
            }
            if (equations[i].charAt(1) == '!' && uf.connected(equations[i].charAt(0) - 'a', equations[i].charAt(3) - 'a') ){
               return false;         
            }
        }     
        return true;
 
    }
    
    class UF {
        int[] id;
        int[] size;
        public UF() {
            id = new int[26];
            size = new int[26];
            
            for (int i = 0; i < 26; i++){
                id[i] = i;
                size[i] = 1;
            }
        }
        public int find(int p){
            while (p != id[p]) {
                id[p] = id[id[p]];
                p = id[p];
            }
            return p;
        }
        public void union(int p, int q) {
            int pRoot = find(p);
            int qRoot = find(q);
            if (pRoot == qRoot) return;
            if (size[pRoot] < size[qRoot]){
                id[pRoot] = qRoot;
                size[qRoot] += size[pRoot];
            }else {
                id[qRoot] = pRoot;
                size[pRoot] += size[qRoot];
            }
        }
        
        public boolean connected(int p, int q) {
            return find(p) == find(q);
        }
    }
}

執行用時 :1 ms, 在所有 Java 提交中擊敗了100.00%的用戶
內存消耗 :39.3 MB, 在所有 Java 提交中擊敗了16.67%的用戶

  • 547 朋友圈(medium)

班上有 N 名學生。其中有些人是朋友,有些則不是。他們的友誼具有是傳遞性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那麼我們可以認爲 A 也是 C 的朋友。所謂的朋友圈,是指所有朋友的集合。

給定一個 N * N 的矩陣 M,表示班級中學生之間的朋友關係。如果M[i][j] = 1,表示已知第 i 個和 j
個學生互爲朋友關係,否則爲不知道。你必須輸出所有學生中的已知的朋友圈總數。

示例 1:

輸入: [[1,1,0], [1,1,0], [0,0,1]] 輸出: 2 說明:已知學生0和學生1互爲朋友,他們在一個朋友圈。
第2個學生自己在一個朋友圈。所以返回2

class Solution {
    //Union Find
    public int findCircleNum(int[][] M) {
        int n = M.length;
        UF uf = new UF(n);
        
        for (int i = 0; i < n; i++) 
            for (int j = 0; j < n; j++) {
                if (M[i][j] == 1)
                    uf.union(i, j);
            }
        
        return uf.count;
        
    }
    class UF {
        int[] id;
        int[] size;
        public int count;
        public UF(int n) {
            id = new int[n];
            size = new int[n];
            count = n;
            for (int i = 0; i < n; i++) {
                id[i] = i;
                size[i] = 1;
            }
        }
        public int find(int p) {
            while (p != id[p]) {
                id[p] = id[id[p]];
                p = id[p];
            }
            return p;
        }
        
        public void union(int p, int q) {
            int pRoot = find(p);
            int qRoot = find(q);
            if (pRoot == qRoot) return;
            if (size[pRoot] < size[qRoot]) {
                id[pRoot] = qRoot;
                size[qRoot] += size[pRoot];
                count--;
            } else {
                id[qRoot] = pRoot;
                size[pRoot] += size[qRoot];
                count--;
            }
        }
    }

DFS解法

public int findCircleNum(int[][] M) {
        int m  = M.length;
        int count = 0;
        int[] visited = new int[m];  //all 0
        
        for (int i = 0; i < m; i++)
            if (visited[i] == 0){
                dfs(M, i, visited);
                count++;
            }

        return count;
    }
    
    public void dfs(int[][] M, int i, int[] visited) {
        for (int j = 0; j < M.length; j++){
            if (visited[j] == 0 && M[i][j] == 1){
                visited[j] = 1;
                dfs(M, j, visited);
            }
        }
          
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章