/*
* 将多个集合合并成没有交集的集合。
给定一个字符串的集合,格式如:{aaa,bbb,ccc},{bbb,ddd},{eee,fff},{ggg},{ddd,hhh}要求将其中交集不为空的集合合并,要求合并完成后的集合之间无交集,
例如上例应输出{aaabbbcccdddhhh},{eeefff},{ggg}。
(1)请描述你解决这个问题的思路;
(2)请给出主要的处理流程,算法,以及算法的复杂度;
(3)请描述可能的改进。
解:
1.对字符集合进行依次编号,分别为[0,1,2,3,4]。如果将{{aaa,bbb,ccc},{bbb,ddd},{eee,fff},{ggg},{ddd,hhh}}看做成二维数组,编号对应二维数组的下标。
初始化一个数组int father[] = {0,1,2,3,4};,代表其下标。
将字符串集合放到list<Set<String>>中集合resList
2.创建一个Map<String,List<Integer>>,key为字符串,value为字符串所在的编号。遍历集合找出每个字符串的编号,如下:
aaa 0
bbb 0,1
ccc 0
ddd 1,4
eee 2
fff 2
ggg 3
hhh 4
3.合并,合并的时候将编号大的集合合并到小的集合里面。方法是:遍历map中的List<Integer>,更新father对应的下表,如下:
aaa 0 {0,1,2,3,4}
bbb 0 1 {0,0,2,3,4}
ccc 0 {0,0,2,3,4}
ddd 1 4 {0,0,2,3,0}
eee 2 {0,0,2,3,0}
fff 2 {0,0,2,3,0}
ggg 3 {0,0,2,3,0}
hhh 4 {0,0,2,3,0}
之后遍历father数组,如果i!=faterh[i],则
Set<String> dest = resList.get(father[i]);
Set<String> sour = resList.get(i);
sour.addAll(dest);
*/
import java.util.List;
import java.util.ArrayList;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Arrays;
public class ShowDisjointSet{
private List<Set<String>> resList = new ArrayList<Set<String>>();
private int[] father;
private int len;
public static void main(String args[]){
String[] str0 = {"aaa","bbb","ccc"};
String[] str1 = {"bbb","ddd"};
String[] str2 = {"eee","fff"};
String[] str3 = {"ggg"};
String[] str4 = {"ddd","hhh"};
String[][] arr = {str0,str1,str2,str3,str4};
ShowDisjointSet obj = new ShowDisjointSet();
obj.getResList(arr);
}
// 1:并查集
public void getResList(String[][] arr){
len = arr.length;
// 初始化resList
for(String[] tmp:arr){
Set<String> set = new HashSet<String>();
set.addAll(Arrays.asList(tmp));
resList.add(set);
}
// 初始化数组
father = new int[len];
for(int i=0;i<len;i++){
father[i] = i;
}
Map<String,List<Integer>> map = getRes(arr);
unionSet(map);
System.out.println(resList);
}
// 2:遍历集合
public Map<String,List<Integer>> getRes(String[][] arr){
Map<String,List<Integer>> map = new HashMap<String,List<Integer>>();
for(int i=0; i<len; i++){
for(String tmp:arr[i]){
if(!map.containsKey(tmp)){
List<Integer> list = new ArrayList<Integer>();
list.add(i);
map.put(tmp,list);
}else{
map.get(tmp).add(i);
}
}
}
return map;
}
// 3:合并集合
public void unionSet(Map<String,List<Integer>> map){
Iterator<Map.Entry<String,List<Integer>>> ite = map.entrySet().iterator();
while(ite.hasNext()){
Map.Entry<String,List<Integer>> entry = ite.next();
String key = entry.getKey();
List<Integer> value = entry.getValue();
unionHelp(value);
System.out.println(key+":"+value);
}
System.out.println("the father array is "+ Arrays.toString(father));
for(int i=0; i<len; i++){
if(i != father[i]){
Set<String> dest = resList.get(father[i]);
Set<String> sour = resList.get(i);
dest.addAll(sour);
}
}
for(int i=0; i<len; i++){
if(i != father[i]){
resList.get(i).clear();
}
}
}
public void unionHelp(List<Integer> list){
int min = getFather(list.get(0));
int size = list.size();
for(int i=0; i<size; i++){
father[list.get(i)] = min;
}
}
public int getFather(int index){
while(index!=father[index]){
index = father[index];
}
return index;
}
}