【算法設計與分析】圖:聯合集/聯合查詢(Union Set/Union Find)

問題說明

聯合查詢主要用於檢查圖裏面是否有迴環。

本文主要圍繞leetcode上的這個題介紹。

聯合集的概念及聯合查詢

聯合集假設初始時,所有的元素都在不同的set內,連接兩個元素後,這兩個元素就屬於同一個set。leetcode684的題就是可以用聯合集來做:
剛開始假設所有的節點都在不同的set內,連接兩個節點之後就設置這兩個節點在同一個set。當新加入的某一條邊的兩個節點都在同一個set,就說明這兩個節點已經可以通過一定的路徑連接了,所以新加入的邊就是冗餘邊。

演示

假設現在有6個節點1-6,我們向這些節點加入邊。初始化時節點及對應的集合如下:

節點 1 2 3 4 5 6
所屬集合 1 2 3 4 5 6

加入邊3-6後的節點及對應集合:

節點 1 2 3 4 5 6
所屬集合 1 2 6 4 5 6

加入邊1-3後的節點及對應集合:

節點 1 2 3 4 5 6
所屬集合 6 2 6 4 5 6

加入邊1-6。加入邊之前可以發現1、6這兩個節點已經屬於同一個set,因此1-6這條邊是冗餘邊。

聯合方法

684涉及到的方法只有兩個:一個是查找一個節點屬於哪個集合;一個是當兩個節點不在同一個set時,將他們歸併到同一個set。

class Solution {
 	public int[] findRedundantConnection(int[][] edges) {
    	int[] us=new int[2000];
    	for(int i=0;i<2000;i++)
    		us[i]=i;
    	
    	for(int[] e:edges) {
    		if(findSet(e[0], us)==findSet(e[1], us))
    			return e;
    		union(e[0],e[1], us);
    	}
    	
    	return null;
    }
 	
 	private int findSet(int num, int[] us) {
 		if(num==us[num])		return num;
 		while(us[num]!=num)
 			num=us[num];
 		return num;
 	}
 	
 	private void union(int start, int end, int[] us) {
 		int startSet = findSet(start, us);
 		int endSet = findSet(end, us);
 		if(startSet!=endSet) {
 			us[startSet]=endSet;
 		}
 	}
 	
}

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