Advertisement
Guest User

Untitled

a guest
Feb 11th, 2017
370
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.43 KB | None | 0 0
  1. import java.util.ArrayList;
  2. import java.util.Arrays;
  3. import java.util.HashMap;
  4. import java.util.HashSet;
  5. import java.util.List;
  6. import java.util.Map;
  7. import java.util.Set;
  8.  
  9. /*
  10. 合并邮件列表(后来才知道也是个面经题)
  11. Given 1 million email list:
  12. list 1: a@a.com, b@b.com
  13. list 2: b@b.com, c@c.com
  14. list 3: e@e.com
  15. list 4: a@a.com
  16. ...
  17. Combine lists with identical emails, and output tuples:
  18. (list 1, list 2, list 4) (a@a.com, b@b.com, c@c.com)
  19. (list 3) (e@e.com)
  20.  
  21.  
  22. Solution:
  23. 1. 假定每个集合编号为0,1,2,3...
  24. 2. 创建一个hash_map,key为字符串,value为一个链表,链表节点为字符串所在集合的编号。遍历所有的集合,将字符串和对应的集合编号插入到hash_map中去。
  25. 3. 创建一个长度等于集合个数的int数组,表示集合间的合并关系。例如,下标为5的元素值为3,表示将下标为5的集合合并到下标为3的集合中去。开始时将所有值
  26. 都初始化为-1,表示集合间没有互相合并。在集合合并的过程中,我们将所有的字符串都合并到编号较小的集合中去。遍历第二步中生成的hash_map,对于每个value
  27. 中的链表,首先找到最小的集合编号(有些集合已经被合并过,需要顺着合并关系数组找到合并后的集合编号),然后将链表中所有编号的集合都合并到编号最小的集
  28. 合中(通过更改合并关系数组)。
  29. 4.现在合并关系数组中值为-1的集合即为最终的集合,它的元素来源于所有直接或间接指向它的集合。
  30. 例子:
  31. 0: {aaa bbb ccc}
  32. 1: {bbb ddd}
  33. 2: {eee fff}
  34. 3: {ggg}
  35. 4: {ddd hhh}
  36. 生成的hash_map,和处理完每个值后的合并关系数组分别为
  37. aaa: 0
  38. bbb: 0, 1
  39. ccc: 0
  40. ddd: 1, 4
  41. eee: 2
  42. fff: 2
  43. ggg: 3
  44. hhh: 4
  45. 所以合并完后有三个集合,第0,1,4个集合合并到了一起,
  46. 第2,3个集合没有进行合并。
  47. */
  48.  
  49. public class MergeEmailLists {
  50.  
  51. public List<Set<String>> mergeEmails(String[][] emails) {
  52. List<Set<String>> result = new ArrayList<Set<String>>();
  53. if(emails == null || emails.length == 0 || emails[0].length == 0) {
  54. return result;
  55. }
  56.  
  57. int m = emails.length;
  58. int[] parent = new int[m]; // initialize parent array, at the begining, each list is in its own group
  59. for(int i=0; i<m; i++) {
  60. parent[i] = i;
  61. }
  62.  
  63. // key: email, value: List of set numbers that email belongs to
  64. Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();
  65. for(int i=0; i<m; i++) {
  66. for(String email : emails[i]) {
  67. if(!map.containsKey(email)) {
  68. List<Integer> list = new ArrayList<Integer>();
  69. list.add(i);
  70. map.put(email, list);
  71. } else {
  72. map.get(email).add(i);
  73. }
  74. }
  75. }
  76.  
  77. // union
  78. for(List<Integer> list : map.values()) {
  79. // list is already in order
  80. for(int i=0; i<list.size(); i++) {
  81. // make larger parent node point to small parent node
  82. union(parent, list.get(0), list.get(i));
  83. }
  84. }
  85.  
  86.  
  87. HashMap<Integer, Set<String>> hash = new HashMap<Integer, Set<String>>();
  88. for(int i=0; i<m; i++) {
  89. hash.put(i, new HashSet<String>());
  90. }
  91. for(int i=0; i<m; i++) {
  92. if(i != parent[i]) {
  93. int p = parent[i];
  94. if(hash.get(p).isEmpty()) {
  95. hash.get(p).addAll(Arrays.asList(emails[p]));
  96. }
  97. hash.get(p).addAll(Arrays.asList(emails[i]));
  98. } else { // 如果parent的值指向自身,说明是单独的集合,直接加入
  99. hash.get(i).addAll(Arrays.asList(emails[i]));
  100. }
  101. }
  102.  
  103. for(Set<String> set : hash.values()) {
  104. if(!set.isEmpty()) {
  105. result.add(set);
  106. }
  107. }
  108. return result;
  109. }
  110.  
  111. public void union(int[] parent, int x, int y) {
  112. int parentX = getParent(parent, x);
  113. int parentY = getParent(parent, y);
  114. if(parentX < parentY) {
  115. parent[parentY] = parentX;
  116. } else if(parentX > parentY) {
  117. parent[parentX] = parentY;
  118. }
  119. }
  120.  
  121. public int getParent(int[] parent, int x) {
  122. while(x != parent[x]) {
  123. parent[x] = parent[parent[x]];
  124. x = parent[x];
  125. }
  126. return x;
  127. }
  128.  
  129. public static void main(String[] args) {
  130. String[] e0 = {"a@a.com", "b@b.com"};
  131. String[] e1 = {"b@b.com", "c@c.com"};
  132. String[] e2 = {"e@e.com"};
  133. String[] e3 = {"a@a.com"};
  134. String[][] emails = {e0, e1, e2, e3};
  135. MergeEmailLists test = new MergeEmailLists();
  136. List<Set<String>> result = test.mergeEmails(emails);
  137. for(Set<String> set : result) {
  138. System.out.println(set);
  139. }
  140. }
  141. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement