[英]If I have a List<Set<Integer>> what is a fast way to remove any sets which are subsets of any other set?
我有一个很大的整数集列表(在Java中)。 我想删除列表中所有其他集合的子集的所有集合。 如果两组相同,则最终列表中仅应保留一组。
显而易见的事情是遍历我的列表,并针对调用某种子集检查方法的所有其他元素检查每个元素。 但这是非常低效的。 有什么我可以做的更好的吗?
我目前正在使用Hashsets和ArrayList,但是如果相关的话,我可以轻松地对其进行更改。
ArrayList可以是任何类型的Collection,因此我认为我可以对Set进行某些操作,至少可以避免使用等效的Integer集。
这是一种方法。
public void method() {
List<Set<Integer>> list = new ArrayList<>();
Set<Integer> a = new HashSet<>();
a.add(1);
a.add(2);
a.add(3);
a.add(4);
a.add(5);
Set<Integer> b = new HashSet<>();
b.add(1);
b.add(2);
b.add(3);
list.add(a);
list.add(b);
System.out.println("Original :" + list);
class SizeComarator implements Comparator<Set<?>> {
@Override
public int compare(Set<?> o1, Set<?> o2) {
return Integer.valueOf(o1.size()).compareTo(o2.size());
}
}
Collections.sort(list, new SizeComarator());
System.out.println("Sorted :" + list);
List<Set<Integer>> result = new ArrayList<>();
for(int i=0; i<list.size(); i++) {
Set<Integer> prev = list.get(i);
boolean flag = false;
for(int j=i+1; j<list.size(); j++) {
if(list.get(j).containsAll(prev))
flag = true;
}
if(!flag)
result.add(prev);
}
System.out.println("Reduced :" + result);
}
这是我根据要求尝试的:
输入数据格式已修改为使用List<int[]>
代替List<Set<Integer>>
。 原因是整数集在此过程中没有更改,并且int[]
可能会更好,我发现它使用起来很简单。 我围绕输入整数集数据创建了一个包装器,作为IntegerSet
并对其进行了处理。
这是代码:
import java.util.*;
import java.util.stream.*;
public class IntegerSetProcess {
public static void main(String[] args) {
// Input data
List<IntegerSet> inputList =
Arrays.asList(new IntegerSet(new int [] {11}),
new IntegerSet(new int [] {12, 555}),
new IntegerSet(new int [] {2, 333, 555, 9, 144, 89}),
new IntegerSet(new int [] {12}),
new IntegerSet(new int [] {12, 3, 555, 90, 42, 789, 15000}),
new IntegerSet(new int [] {2, 555, 9, 89, 333, 144}),
new IntegerSet(new int [] {555, 12}),
new IntegerSet(new int [] {222, 12, 41320, 0, 769942}),
new IntegerSet(new int [] {910, 77}));
// Distinct IntegerSets
List<IntegerSet> distinctList =
inputList.stream()
.distinct()
.sorted()
.collect(Collectors.toList());
// Filter subsets to get result
List<IntegerSet> resultList = doSubsetFiltering(distinctList);
// Result data in original form (optional)
resultList.stream()
.forEach(e -> System.out.println(Arrays.toString(e.getOriginal())));
}
/*
* Takes the input List<IntegerSet> and removes all the IntegerSets with
* elements as subset in any other IntegerSet.
*/
private static List<IntegerSet> doSubsetFiltering(List<IntegerSet> listIs) {
List<IntegerSet> removedIs = new ArrayList<>();
OUTER_LOOP: // size-1, the last element is not iterated
for (int i = 0; i < listIs.size()-1; i++) {
IntegerSet thisIs = listIs.get(i);
INNER_LOOP: // i+1, the checking starts from the next IntegerSet
for (int j = i+1; j < listIs.size(); j++) {
IntegerSet nextIs = listIs.get(j);
if (isSubset(thisIs.getData(), nextIs.getData())) {
// To remove thisIs set as it is a subset of isNext
removedIs.add(thisIs);
break INNER_LOOP;
}
} // inner-for-loop
} // outer for-loop
listIs.removeAll(removedIs);
return listIs;
}
// Returns true if the input array thisIs has all its elements in nextIs.
public static boolean isSubset(int[] thisIs, int[] nextIs) {
for(int i : thisIs) {
if (Arrays.binarySearch(nextIs, i) < 0) {
return false;
}
}
return true;
}
}
import java.util.*;
import java.util.stream.*;
public class IntegerSet implements Comparable<IntegerSet> {
private int[] data;
private int[] original;
public IntegerSet(int[] intput) {
original = IntStream.of(intput).toArray();
data = intput;
Arrays.sort(data);
}
public int[] getData() {
return data;
}
public int[] getOriginal() {
return original;
}
@Override
public String toString() {
return Arrays.toString(data);
}
@Override
public boolean equals(Object obj) {
IntegerSet is = (IntegerSet) obj;
if (Arrays.equals(data, is.getData())) {
return true;
}
return false;
}
@Override
public int hashCode() {
return data.length;
}
@Override
public int compareTo(IntegerSet is) {
return Integer.valueOf(data.length).compareTo(is.getData().length);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.