繁体   English   中英

如果我有清单 <Set<Integer> &gt;删除属于任何其他集合子集的任何集合的快速方法是什么?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM