1、问题描述

将多个集合合并成没有交集的集合。
给定一个字符串的集合,格式如:{aaa bbb ccc}, {bbb ddd},{eee fff},{ggg},{ddd hhh}要求将其中交集不为空的集合合并,要求合并完成后的集合之间无交集,例如上例应输出{aaa bbb ccc ddd hhh},{eee fff}, {ggg}。
(1)请描述你解决这个问题的思路;
(2)请给出主要的处理流程,算法,以及算法的复杂度
(3)请描述可能的改进。

2、分析

1. 假定每个集合编号为0,1,2,3...
    2. 创建一个hash_map,key为字符串,value为一个链表,链表节点为字符串所在集合的编号。遍历所有的集合,将字符串和对应的集合编号插入到hash_map中去。
    3. 创建一个长度等于集合个数的int数组,表示集合间的合并关系。例如,下标为5的元素值为3,表示将下标为5的集合合并到下标为3的集合中去。开始时将所有值都初始化为-1,表示集合间没有互相合并。在集合合并的过程中,我们将所有的字符串都合并到编号较小的集合中去。
    遍历第二步中生成的hash_map,对于每个value中的链表,首先找到最小的集合编号(有些集合已经被合并过,需要顺着合并关系数组找到合并后的集合编号),然后将链表中所有编号的集合都合并到编号最小的集合中(通过更改合并关系数组)。
    4.现在合并关系数组中值为-1的集合即为最终的集合,它的元素来源于所有直接或间接指向它的集合。
    0: {aaa bbb ccc}
    1: {bbb ddd}
    2: {eee fff}
    3: {ggg}
    4: {ddd hhh}
    生成的hash_map,和处理完每个值后的合并关系数组分别为
    aaa: 0           
    bbb: 0, 1        
    ccc: 0          
    ddd: 1, 4       
    eee: 2           
    fff: 2          
    ggg: 3           
    hhh: 4          
    所以合并完后有三个集合,第0,1,4个集合合并到了一起,
    第2,3个集合没有进行合并。

3、具体实现

   1: class DisjointSetProblem {
   2:     private final int SIZE = 7;
   3:     private int[] father;  
   4:     private static List<Set<String>> resultList = new ArrayList<Set<String>>();
   5:  
   6:     public static void main(String[] args) {
   7:         String[] str0 = { "aaa", "bbb", "ccc", };
   8:         String[] str1 = { "bbb", "ddd", };
   9:         String[] str2 = { "eee", "fff", };
  10:         String[] str3 = { "ggg", };
  11:         String[] str4 = { "ddd", "hhh", };
  12:         String[] str5 = { "xx", "yy", };
  13:         String[] str6 = { "zz", "yy", };
  14:         String[][] strs = { str0, str1, str2, str3, str4, str5, str6 };
  15:         //change String[][] to List<Set>  
  16:         for (String[] str : strs) {
  17:             //when I write--"Arraylist list=Arrays.asList(strArray)","addAll()" is unsupported for such a arraylist.  
  18:             Set<String> set = new HashSet<String>();
  19:             set.addAll(Arrays.asList(str));
  20:             resultList.add(set);
  21:         }
  22:         DisjointSetProblem disjointSet = new DisjointSetProblem();
  23:         disjointSet.disjoin(strs);
  24:     }
  25:  
  26:     /*
  27:      * 获取hashmap过程
  28:      * */
  29:     public void disjoin(String[][] strings) {
  30:         if (strings == null || strings.length < 2)
  31:             return;
  32:         initial();
  33:         // 获得hash_map:key为字符串,value为一个链表
  34:         Map<String, List<Integer>> map = storeInHashMap(strings);
  35:         // 并查集进行合并
  36:         union(map);
  37:     }
  38:  
  39:     //in the beginning,each element is in its own "group".  
  40:     public void initial() {
  41:         father = new int[SIZE];
  42:         for (int i = 0; i < SIZE; i++) {
  43:             father[i] = i;
  44:         }
  45:     }
  46:  
  47:     /* Map<k,v> 
  48:      * key:String 
  49:      * value:List<Integer>-in which sets the string shows up. 
  50:      */
  51:     public Map<String, List<Integer>> storeInHashMap(String[][] strings) {
  52:         Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();
  53:         for (int i = 0; i < SIZE; i++) {
  54:             for (String each : strings[i]) {
  55:                 if (!map.containsKey(each)) {
  56:                     List<Integer> list = new ArrayList<Integer>();
  57:                     list.add(i);
  58:                     map.put(each, list);
  59:                 } else {
  60:                     map.get(each).add(i);
  61:                 }
  62:             }
  63:         }
  64:  
  65:         // 打印出map
  66:         System.out.println("集合映射所生成的hashmap为:");
  67:         printMap(map);
  68:         return map;
  69:     }
  70:  
  71:     private void printMap(Map<String, List<Integer>> map) {
  72:         // TODO Auto-generated method stub
  73:         Iterator<Map.Entry<String, List<Integer>>> iter = map.entrySet()
  74:                 .iterator();
  75:         while (iter.hasNext()) {
  76:             Map.Entry<String, List<Integer>> entry = iter.next();
  77:             String key = entry.getKey();
  78:             List<Integer> value = entry.getValue();
  79:             System.out.println(key + ":" + value);
  80:         }
  81:         System.out.println();
  82:     }
  83:  
  84:     /*
  85:      * 对hashmap进行并查集合并操作
  86:      * */
  87:     public void union(Map<String, List<Integer>> map) {
  88:         Iterator<Map.Entry<String, List<Integer>>> it = map.entrySet()
  89:                 .iterator();
  90:         while (it.hasNext()) {
  91:             Map.Entry<String, List<Integer>> entry = it.next();
  92:             List<Integer> value = entry.getValue();
  93:             unionHelp(value);//the arrays whose indexes are in the same list should be merged to one set.             
  94:         }
  95:         // 打印出father父节点信息
  96:         System.out.println("hashmap集合合并之后的父节点信息为:");
  97:         printFather(father);//System.out.println("the father array is " + Arrays.toString(father));
  98:         printSetList(resultList);
  99:         //merge two sets  
 100:         for (int i = 0; i < SIZE; i++) {
 101:             if (i != father[i]) {
 102:                 // set:无重复元素
 103:                 Set<String> dest = resultList.get(father[i]);
 104:                 Set<String> source = resultList.get(i);
 105:                 dest.addAll(source);
 106:             }
 107:         }
 108:         //clear a set which has been added.  
 109:         // 当B集合添加到A集合后,清空B集合
 110:         for (int i = 0; i < SIZE; i++) {
 111:             if (i != father[i]) {
 112:                 resultList.get(i).clear();
 113:             }
 114:         }
 115:         System.out.println("合并后:" + resultList);
 116:     }
 117:  
 118:     public void unionHelp(List<Integer> list) {
 119:         int minFather = getFather(list.get(0));//list[0] is the smaller.  
 120:         // 传过来的list参数已经排好序
 121:         for (int i = 0, size = list.size(); i < size; i++) {
 122:             //father[list.get(i)] = minFather;
 123:             unionHelp(list.get(0),list.get(i));
 124:         }
 125:     }
 126:  
 127:     // 路径压缩
 128:     public int getFather(int x) {
 129:         while (x != father[x]) {
 130:             x = father[x];
 131:         }
 132:         return x;
 133:     }    
 134:  
 135:     private void printFather(int[] fatherNode) {
 136:         // TODO Auto-generated method stub
 137:         for (int node : fatherNode)
 138:             System.out.print(node + " ");
 139:         System.out.println();
 140:     }
 141:  
 142:     private void printSetList(List<Set<String>> list) {
 143:         // TODO Auto-generated method stub
 144:         System.out.print("合并前:");
 145:         for (int i = 0; i < SIZE; i++) {
 146:             System.out.print(list.get(i) + " ");
 147:         }
 148:         System.out.println();
 149:     }
 150:  
 151:     //general union in disjoin set.But we overload it in this case.  
 152:     public void unionHelp(int x, int y) {
 153:         if (father[x] != father[y]) {
 154:             int fx = getFather(x);
 155:             int fy = getFather(y);
 156:             //merge two arrays to the array that has a smaller index.  
 157:             if (fx < fy) {
 158:                 father[y] = fx;
 159:             } else {
 160:                 father[x] = fy;
 161:             }
 162:         }
 163:     }
 164:     
 165: }

转载于:https://www.cnblogs.com/ttltry-air/archive/2012/08/14/2638437.html

多个集合合并成没有交集的集合-实现相关推荐

  1. 将多个集合合并成没有交集的集合

    百度面试题:将多个集合合并成没有交集的集合 2010-03-20 18:25 给定一个字符串的集合,格式如:{aaa bbb ccc}, {bbb ddd},{eee fff},{ggg},{ddd ...

  2. 【转】面试题:将多个集合合并成没有交集的集合

    原文地址:http://blog.sina.com.cn/s/blog_4d3a41f401011bxd.html 给定一个字符串的集合,格式如:{aaa bbb ccc}, {bbb ddd},{e ...

  3. java jdk8 使用stream实现两个list集合合并成一个list集合(对象属性的合并)

    java使用stream实现list中对象属性的合并: 根据两个List中的某个相同字段合并成一条List,包含两个List中的字段 目录 一.前言 二.示例 示例1:java8 合并两个 list& ...

  4. Java中,通过synchronizedXxx()将线程不安全的集合转换成线程安全的集合

    保证线程安全的方法 synchronizedXxx():该方法可以使指定的集合包装成线程安全的集合,并返回 例如: Collections.synchronizedList(List) 将线程不安全的 ...

  5. Java把一个大集合拆分成多个小集合,可以利用多线程提升并发处理效率

    场景: 在开发中,如果一个集合中的数据量特别大,那么对这个集合进行循环处理业务可能就会比较耗时,为了提升效率,可以考虑把大集合拆分成多个小集合,然后用多线程对拆分后的多个小集合进行处理 拆分: 1.拆 ...

  6. 把list集合转换成另一个list集合的三个方法

    1.把list集合转换成另一个list集合方法1,使用jdk1.8流 List<ModelInputNode.ModelColumns> modelColumns=standardTabl ...

  7. 一个对象的集合转化成另一个对象的集合 PO集合转换为VO集合

    一个对象的集合转化成另一个对象的集合 PO集合转换为VO集合 准备数据 import com.google.common.base.Function; import com.google.common ...

  8. Java8两个list集合合并成一个list集合

    为什么要用Lambda表达式和Stream流做集合的处理? 因为效率高.代码简洁.高端大气上档次啊! ES6 1.将一个集合中每一个对象的某个元素取出来作为一个新的集合var newList = ol ...

  9. 两个List数据集合合并成一个List

    查询两个差不多相同的表,一个是入库表,一个是退货表,字段大致相同,但是有所差异,入库表的数量和所有金额都是正数,退货表的数量和金额都是负数,所以不能join链表查询,需要分开查询出两个ToList:但 ...

最新文章

  1. PTA基础编程题目集-7-1 厘米换算英尺英寸
  2. R语言使用fs包的file_info函数查看文件元信息(属性信息)、使用file_chmod函数修改文件的权限、使用file_chown函数修改文件的所有者
  3. python opencv实时显示测量数据_python OpenCV 宽度测量
  4. 三维动画制作的基本流程
  5. Android多线程源码学习笔记一:handler、looper、message、messageQueue
  6. CentOS 6.5 部署WordPress
  7. HTML怎么做类似QQ聊天气泡,h5实现QQ聊天气泡的实例介绍
  8. [渝粤题库]陕西师范大学《商业银行经营学》作业
  9. java获取对象的子_java – 如何根据子对象字段获取父对象
  10. Linux之vi 文本编辑命令
  11. 力扣--260只出现一次的数字I-III
  12. 智能优化算法应用:基于麻雀搜索算法与双伽马校正的图像自适应增强算法 - 附代码
  13. github客户端从gitLab下拉取代码
  14. 甘超波:NLP五步觉察法
  15. 警报声.wav_具有中央警报缓存的jAlarms 1.4
  16. python归一化 增大差异_python-面向对象进阶
  17. PADS的四层板转换成2层板
  18. 常用的web服务器软件有哪些
  19. 【网络安全学习之零基础】
  20. Fallout 4 辐射4 技巧统计

热门文章

  1. linux编译bzip2,linux bzip2 命令详解
  2. Java笔记-CXF使用Adapter处理复杂类型(如Map)
  3. NginxJava笔记-Webservice使用HTTPS协议及Spring Boot配置tomcat
  4. TCP/IP学习笔记-Qt中的ReuseAddressHint以及SO_REUSEADDR,以为组播常用场景分析
  5. 随机邻域嵌入_图嵌入(Graph embedding)综述
  6. flyway常用配置_Spring Boot 2.x基础教程:使用Flyway管理数据库版本
  7. java生成验证码SWT_Java SWT Lable框中显示图片验证码
  8. 去年计算机试题,微机去年试卷及答案,广东海洋大学
  9. mysql80连接不上本地服务器_小白教程:ubuntu服务器安装jupyter notebook, 并能够实现本地远程连接
  10. git tag怎么使用_GIT中tag使用,打版本必备