标签:void size 去重 ext ini als final boolean 而且
有一个集合组成的list,如果有两个集合有相同的元素,将他们合并。返回最后还剩下几个集合。
1000
。m <= 100
。100000
。样例1:
输入:list = [[1,2,3],[3,9,7],[4,5,10]]
输出:2 .
样例:剩下[1,2,3,9,7]和[4,5,10]这2个集合。
样例 2:
输入:list = [[1],[1,2,3],[4],[8,7,4,5]]
输出 :2
解释:剩下[1,2,3]和[4,5,7,8] 2个集合。
一开始想直接暴力,后面发现会超时,就往并查集方向想,想将所有的数都设置一个所属的数组下标(相当于祖先节点),然后搜索一遍,如果相同的数的对应的数组下标不同,那么就合并这两个数所在的两个数组,当时没有想到给这个二维数组构造一个一维数组list然后对它按数进行从小到大排序,所以才导致了后面的结果出错。那么为啥要排序呢?因为经过排序之后,相同的数会靠在一起,这样就利于合并两个数组了,用一个while循环,只要遇到两个相同的数,而且这两个数对应的数组下标inde不相等,那么就将后面数所在数组的所有数合并,直到没有相同的数不在同一个数组之后就跳出while循环。最后统计一下list数组中有多少个不同的数下标(这里可以将list中的所有数依次遍历并添加到set集合中,因为set集合可以去重)即可。
1 import java.util.*; 2 3 public class Solution { 4 5 public int setUnion(int[][] sets) { 6 if (sets == null || sets.length == 0) { 7 return 0; 8 } 9 10 int n = sets.length; 11 12 for (int i = 0; i < n - 1; i++) { 13 for (int j = i + 1; j < n; j++) { 14 if (sets[i] == null || sets[j] == null) { 15 continue; 16 } 17 if (find(sets[i], sets[j])) { 18 sets[i] = union(sets[i], sets[j]); 19 sets[j] = null; 20 // 回溯 21 i = -1; 22 break; 23 } 24 } 25 } 26 27 int count = 0; 28 for (int i = 0; i < sets.length; i++) { 29 if (sets[i] != null) { 30 count++; 31 } 32 } 33 34 return count; 35 } 36 37 // 合并 38 public int[] union(int[] a, int[] b) { 39 Set<Integer> set = new HashSet<>(); 40 41 for (int i = 0; i < a.length; i++) { 42 set.add(a[i]); 43 } 44 for (int i = 0; i < b.length; i++) { 45 set.add(b[i]); 46 } 47 48 int[] union = new int[set.size()]; 49 Iterator<Integer> iterator = set.iterator(); 50 int index = 0; 51 while (iterator.hasNext()) { 52 union[index++] = iterator.next(); 53 } 54 55 return union; 56 } 57 58 // 查询 59 public boolean find(int[] a, int[] b) { 60 for (int i = 0; i < a.length; i++) { 61 for (int j = 0; j < b.length; j++) { 62 if (a[i] == b[j]) { 63 return true; 64 } 65 } 66 } 67 68 return false; 69 } 70 }
1 import java.util.*; 2 3 public class Solution { 4 5 /** 6 * 键值对类 7 */ 8 class MyMap { 9 int val; 10 int index; 11 12 public MyMap(int val, int index) { 13 this.val = val; 14 this.index = index; 15 } 16 } 17 18 /** 19 * @param sets: 20 * Initial set list 21 * @return: The final number of sets 22 */ 23 public int setUnion(int[][] sets) { 24 // Write your code here 25 if (sets == null || sets.length == 0) { 26 return 0; 27 } 28 29 int n = sets.length; 30 31 // 注意:一定要排序,才能用这种方法 32 // 定义一个MyMap类,val表示当前数,index表示当前数所在的数组的下标 33 List<MyMap> list = new ArrayList<>(); 34 for (int i = 0; i < n; i++) { 35 for (int j = 0; j < sets[i].length; j++) { 36 list.add(new MyMap(sets[i][j], i)); 37 } 38 } 39 40 // 排序 41 Collections.sort(list, new Comparator<MyMap>() { 42 43 @Override 44 public int compare(MyMap o1, MyMap o2) { 45 if (o1.val > o2.val) { 46 return 1; 47 } else if (o1.val < o2.val){ 48 return -1; 49 } else { 50 return 0; 51 } 52 } 53 54 }); 55 56 // 保存两个相同数的后一个数在list集合中的下标 57 int endIndex; 58 // 一直循环判断,直到没有相同的数为止,跳出循环 59 while ((endIndex = check(list)) != -1) { 60 int src = list.get(endIndex).index; 61 int target = list.get(endIndex - 1).index; 62 union(list, src, target); 63 } 64 65 Set<Integer> set = new HashSet<>(); 66 for (int i = 0; i < list.size(); i++) { 67 set.add(list.get(i).index); 68 } 69 70 return set.size(); 71 } 72 73 // 返回要修改的那个数在list集合中的下标 74 public int check(List<MyMap> list) { 75 for (int i = 1; i < list.size(); i++) { 76 // 跟前面一个数比 77 // 如果当前数跟前面一个数相等,但是所在集合不是同一个,那么就要合并,并返回当前数所在的数组下标 78 if (list.get(i).val == list.get(i - 1).val && list.get(i).index != list.get(i - 1).index) { 79 return i; 80 } 81 } 82 83 // 如果没有相等的数不在同一个数组中的话,那么就返回-1,即表示不需要合并 84 return -1; 85 } 86 87 public void union(List<MyMap> list, int src, int target) { 88 for (int i = 0; i < list.size(); i++) { 89 if (list.get(i).index == src) { 90 list.get(i).index = target; 91 } 92 } 93 } 94 }
LintCode链接:https://www.lintcode.com/problem/1396/
标签:void size 去重 ext ini als final boolean 而且
原文地址:https://www.cnblogs.com/pengsay/p/14659516.html