323. Number of Connected Components in an Undirected Graph

Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), write a function to find the number of connected components in an undirected graph.
Example 1:

     0          3
     |          |
     1 --- 2    4
Given n = 5 and edges = [[0, 1], [1, 2], [3, 4]], return 2.

Example 2:

     0           4
     |           |
     1 --- 2 --- 3
Given n = 5 and edges = [[0, 1], [1, 2], [2, 3], [3, 4]], return 1.

Note:
You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges.

類似200 Number of Islands: http://www.reibang.com/p/f834dbd46dd3

Solution1:Union Find

思路: Typical union find
1_a: routine
1_b: short version
Time Complexity: O(ElogV) ? Space Complexity: O(V)

Solution2:DFS (recursive)

思路: dfs visit暂衡,跳過已經(jīng)visit的垫桂,記錄遍歷中visit的次數(shù)作為結(jié)果
Time Complexity: O(E+V) Space Complexity: O(E+V)

Solution3:DFS (stack)

思路: dfs visit暇藏,跳過已經(jīng)visit的堤魁,記錄遍歷中visit的次數(shù)作為結(jié)果,思路同2防症,stack實現(xiàn)婆誓。
Time Complexity: O(E+V) Space Complexity: O(E+V)

Solution4:BFS (queue)

思路: dfs visit,跳過已經(jīng)visit的吠撮,記錄遍歷中visit的次數(shù)作為結(jié)果,思路同讲竿。
實現(xiàn)同3泥兰,將stack改為queue即可。
Time Complexity: O(E+V) Space Complexity: O(E+V)

Solution1a Code:

class Solution {
    
    class UF {
        private int[] id;  
        private int[] sz;  // for an id, the number of elements in that id
        private int count; // number of sort of id

        public UF(int n) {
            
            this.id = new int[n];
            this.sz = new int[n];
            this.count = 0;
            
            // init
            for (int i = 0; i < n; i++) {
                this.id[i] = i;
                this.sz[i] = 1;
                this.count++;
            }
        }

        public void union(int p, int q) {
            int p_root = find(p), q_root = find(q);
            // weighted quick union
            ///*
            if(p_root == q_root) return;
            if (sz[p_root] < sz[q_root]) { 
                id[p_root] = q_root; sz[q_root] += sz[p_root];
            } else {
                id[q_root] = p_root; sz[p_root] += sz[q_root];
            }
            --count;
            //*/
            
            // regular
            /*
            if(p_root == q_root) return;
            id[p_root] = q_root;
            --count;
            */
        }

        public int find(int i) { // path compression
            for (;i != id[i]; i = id[i])
                id[i] = id[id[i]]; 
            return i;
        }

        public boolean connected(int p, int q) {
            int p_root = find(p);
            int q_root = find(q);
            if(p_root != q_root) return false;
            else return true;
        }

        public int count() { 
            return this.count; 
        }
        
    }
    
    public int countComponents(int n, int[][] edges) {
        UF uf = new UF(n); 

        for(int[] e : edges) {
            int root1 = uf.find(e[0]);
            int root2 = uf.find(e[1]);
            if(root1 != root2) {      
                uf.union(root1, root2);
            }
        }
        return uf.count();
    }

}
class Solution {
    
    public int countComponents(int n, int[][] edges) {
        int[] roots = new int[n];
        for(int i = 0; i < n; i++) roots[i] = i; 

        for(int[] e : edges) {
            int root1 = find(roots, e[0]);
            int root2 = find(roots, e[1]);
            if(root1 != root2) {      
                roots[root1] = root2;  // union
                n--;
            }
        }
        return n;
    }

    public int find(int[] roots, int id) {
        while(roots[id] != id) {
            roots[id] = roots[roots[id]];  // optional: path compression
            id = roots[id];
        }
        return id;
    }

}

Solution1b Code:

class Solution {
    public int countComponents(int n, int[][] edges) {
        int[] roots = new int[n];
        for(int i = 0; i < n; i++) roots[i] = i; 

        for(int[] e : edges) {
            int root1 = find(roots, e[0]);
            int root2 = find(roots, e[1]);
            if(root1 != root2) {      
                roots[root1] = root2;  // union
                n--;
            }
        }
        return n;
    }

    public int find(int[] roots, int id) {
        while(roots[id] != id) {
            roots[id] = roots[roots[id]];  // optional: path compression
            id = roots[id];
        }
        return id;
    }

}

Solution2 Code:

public class Solution {
    
    public int countComponents(int n, int[][] edges) {
        if (n <= 1) {
            return n;
        }
        
        // graph = adj_list init
        List<List<Integer>> graph = new ArrayList<List<Integer>>();
        for(int i = 0; i < n; i++) {
            graph.add(new ArrayList<Integer>()); // LinkedList is also OK
        }

        // graph(adj_list) build
        // i -> j node pairs
        for (int i = 0; i < edges.length; i++) {
            int pre = edges[i][0];
            int post = edges[i][1];
            graph.get(pre).add(post); 
            graph.get(post).add(pre);
        }
        
        boolean visited[] = new boolean[n];
        int count = 0;
        for(int i = 0; i < n; i++) {
            if(!visited[i]) {
                dfs(graph, i, visited);
                count++;
            }
        }
        
        return count;
    }
    
    private void dfs(List<List<Integer>> graph, int start, boolean[] visited) {
        visited[start] = true;
        for (int des : graph.get(start)) {
            if(!visited[des]) {
                dfs(graph, des, visited);
            }
        }
    }
}

Solution3 Code:

public class Solution {
    
    public int countComponents(int n, int[][] edges) {
        if (n <= 1) {
            return n;
        }
        
        // graph = adj_list init
        List<List<Integer>> graph = new ArrayList<List<Integer>>();
        for(int i = 0; i < n; i++) {
            graph.add(new ArrayList<Integer>()); // LinkedList is also OK
        }

        // graph(adj_list) build
        // i -> j node pairs
        for (int i = 0; i < edges.length; i++) {
            int pre = edges[i][0];
            int post = edges[i][1];
            graph.get(pre).add(post); 
            graph.get(post).add(pre);
        }
        
        boolean visited[] = new boolean[n];
        int count = 0;
        for(int i = 0; i < n; i++) {
            if(!visited[i]) {
                dfs(graph, i, visited);
                count++;
            }
        }
        
        return count;
    }
    
    private void dfs(List<List<Integer>> graph, int start, boolean[] visited) {
        Deque<Integer> stack = new ArrayDeque<Integer>();
        
        stack.push(start);
        visited[start] = true;
        
        while(!stack.isEmpty())  
        {
            int from = stack.pop();
            for(int des : graph.get(from)) {
                if(visited[des]) continue;
                stack.push(des);
                visited[des] = true;
            }
        }
    }
}

Solution4 Code:

public class Solution {
    
    public int countComponents(int n, int[][] edges) {
        if (n <= 1) {
            return n;
        }
        
        // graph = adj_list init
        List<List<Integer>> graph = new ArrayList<List<Integer>>();
        for(int i = 0; i < n; i++) {
            graph.add(new ArrayList<Integer>()); // LinkedList is also OK
        }

        // graph(adj_list) build
        // i -> j node pairs
        for (int i = 0; i < edges.length; i++) {
            int pre = edges[i][0];
            int post = edges[i][1];
            graph.get(pre).add(post); 
            graph.get(post).add(pre);
        }
        
        boolean visited[] = new boolean[n];
        int count = 0;
        for(int i = 0; i < n; i++) {
            if(!visited[i]) {
                dfs(graph, i, visited);
                count++;
            }
        }
        
        return count;
    }
    
    private void dfs(List<List<Integer>> graph, int start, boolean[] visited) {
        Queue<Integer> queue = new LinkedList<Integer>();
        
        queue.offer(start);
        visited[start] = true;
        
        while(!queue.isEmpty())  
        {
            int from = queue.poll();
            for(int des : graph.get(from)) {
                if(visited[des]) continue;
                queue.offer(des);
                visited[des] = true;
            }
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末题禀,一起剝皮案震驚了整個濱河市鞋诗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌投剥,老刑警劉巖师脂,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件担孔,死亡現(xiàn)場離奇詭異江锨,居然都是意外死亡吃警,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進店門啄育,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酌心,“玉大人,你說我怎么就攤上這事挑豌“踩” “怎么了?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵氓英,是天一觀的道長侯勉。 經(jīng)常有香客問我,道長铝阐,這世上最難降的妖魔是什么址貌? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮徘键,結(jié)果婚禮上练对,老公的妹妹穿的比我還像新娘。我一直安慰自己吹害,他們只是感情好螟凭,可當我...
    茶點故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著它呀,像睡著了一般螺男。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上钟些,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天烟号,我揣著相機與錄音,去河邊找鬼政恍。 笑死汪拥,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的篙耗。 我是一名探鬼主播迫筑,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼宗弯!你這毒婦竟也來了脯燃?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤蒙保,失蹤者是張志新(化名)和其女友劉穎辕棚,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡逝嚎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年扁瓢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片补君。...
    茶點故事閱讀 40,861評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡引几,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出挽铁,到底是詐尸還是另有隱情伟桅,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布叽掘,位于F島的核電站楣铁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏更扁。R本人自食惡果不足惜民褂,卻給世界環(huán)境...
    茶點故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望疯潭。 院中可真熱鬧赊堪,春花似錦、人聲如沸竖哩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽相叁。三九已至遵绰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間增淹,已是汗流浹背椿访。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留虑润,地道東北人成玫。 一個月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像拳喻,于是被迫代替她去往敵國和親哭当。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,860評論 2 361

推薦閱讀更多精彩內(nèi)容