【问题标题】:The intersection of all combinations of n listsn 个列表的所有组合的交集
【发布时间】:2021-04-23 01:27:52
【问题描述】:

给定一个大小大于 3 的 ArrayList 的 ArrayList

ArrayList<ArrayList<Integer>> lists = new ArrayLists<ArrayList<Integer>>();

我想获取 3 个唯一的子列表,找到它们的交集,然后对所有可能的组合重复此过程。下面是伪代码

public void generateIntersections(ArrayLists<ArrayList<Integer>> lists) {
    if (lists.size() > 3) {
        int n = lists.size();
        //number of combinations theoretically, `!` is wrong I know
        int numberOfCombinations = n! / (3!(n - 3)!);
        while (numberOfCombinations) {
            // unique items
            ArrayList<Integer> list 1 = lists.get(?);
            ArrayList<Integer> list 2 = lists.get(?);
            ArrayList<Integer> list 3 = lists.get(?);

            Set<Integer> = intersection(list1, list2, list3);
        }
    }
}

我对这个问题感到困惑,因为我不确定如何在迭代时正确跟踪三个计数器。在这种特殊情况下,正确实施组合而不是排列的概念进一步阻碍了我。

我尝试了很多方法,但在每种情况下,我的代码都会很快变得毫无意义。我想我缺乏一些特别的技巧。也许涉及到 HashSet?

【问题讨论】:

    标签: java arraylist combinations set-intersection


    【解决方案1】:

    Java 7 中的交叉路口地图

    处理原始列表的三个步骤:首先为每个元素收集一个交叉点图Map&lt;Integer,Set&lt;Integer&gt;&gt;,然后为这个图收集一个交叉点图Map&lt;Set&lt;Integer&gt;,Set&lt;Integer&gt;&gt;,然后将较大的交叉点集合附加到较小的交叉点如果它们相交,则设置。

    Try it online!

    原始列表List&lt;List&lt;Integer&gt;&gt;

    List 0: [1, 2, 6, 5, 4, 3]
    List 1: [3, 7, 2, 9, 5, 4]
    List 2: [2, 6, 7, 1, 4]
    

    1 - 路口地图Map&lt;Integer,Set&lt;Integer&gt;&gt;:

    Element: 1 is in lists: [0, 2]
    Element: 2 is in lists: [0, 1, 2]
    Element: 3 is in lists: [0, 1]
    Element: 4 is in lists: [0, 1, 2]
    Element: 5 is in lists: [0, 1]
    Element: 6 is in lists: [0, 2]
    Element: 7 is in lists: [1, 2]
    Element: 9 is in lists: [1]
    

    2 - 交叉路口的地图Map&lt;Set&lt;Integer&gt;,Set&lt;Integer&gt;&gt;

    Lists: [0, 1, 2] contain elements: [2, 4]
    Lists: [0, 1] contain elements: [3, 5]
    Lists: [0, 2] contain elements: [1, 6]
    Lists: [1, 2] contain elements: [7]
    

    3 - 将较大的交叉点集附加到较小的交叉点集(如果它们相交)后的交叉点图:

    Lists: [0, 1, 2] contain elements: [2, 4]
    Lists: [0, 1] contain elements: [2, 3, 4, 5]
    Lists: [0, 2] contain elements: [1, 2, 4, 6]
    Lists: [1, 2] contain elements: [2, 4, 7]
    

    Java 7 代码:

    List<List<Integer>> lists = Arrays.asList(
            Arrays.asList(1, 2, 6, 5, 4, 3),
            Arrays.asList(3, 7, 2, 9, 5, 4),
            Arrays.asList(2, 6, 7, 1, 4));
    
    // map of intersections:
    // key - element of the list,
    // value - set of indexes of lists,
    // i.e. where this element occurs
    Map<Integer, Set<Integer>> map1 = new TreeMap<>();
    for (int i = 0; i < lists.size(); i++) {
        // output the original list
        System.out.println("List " + i + ": " + lists.get(i));
        for (int element : lists.get(i)) {
            // pull out the set of intersections
            Set<Integer> set = map1.remove(element);
            // create it if it doesn't exist
            if (set == null) set = new TreeSet<>();
            // add index of current list
            set.add(i);
            // put into the map
            map1.put(element, set);
        }
    }
    
    // intermediate output
    for (Map.Entry<Integer, Set<Integer>> entry : map1.entrySet())
        System.out.println("Element: " + entry.getKey()
                + " is in lists: " + entry.getValue());
    
    // custom comparator for the map of intersections of intersections
    Comparator<Set<Integer>> comparator = new Comparator<Set<Integer>>() {
        @Override
        public int compare(Set<Integer> o1, Set<Integer> o2) {
            // group intersections that are equal
            if (o1.containsAll(o2) && o2.containsAll(o1)) return 0;
            // compare by number of intersections in reverse order
            int val = Integer.compare(o2.size(), o1.size());
            if (val != 0) return val;
            // if sizes are equal compare hashCodes
            return Integer.compare(o1.hashCode(), o2.hashCode());
        }
    };
    
    // map of intersections of intersections:
    // key - set of indexes of lists
    // value - set of elements
    TreeMap<Set<Integer>, Set<Integer>> map2 = new TreeMap<>(comparator);
    for (Map.Entry<Integer, Set<Integer>> entry : map1.entrySet()) {
        // set of intersecting elements
        Set<Integer> key = entry.getValue();
        // filter out unique elements
        if (key.size() == 1) continue;
        // pull out the set of intersecting elements
        Set<Integer> value = map2.remove(key);
        // create it if it doesn't exist
        if (value == null) value = new TreeSet<>();
        // add current element
        value.add(entry.getKey());
        // put into the map
        map2.put(key, value);
    }
    
    // intermediate output
    for (Map.Entry<Set<Integer>, Set<Integer>> entry : map2.entrySet())
        System.out.println("Lists: " + entry.getKey()
                + " contain elements: " + entry.getValue());
    
    // append the larger intersections sets to the
    // smaller intersections sets if they intersect
    for (Map.Entry<Set<Integer>, Set<Integer>> entry : map2.entrySet()) {
        // for each entry process the values of other
        // entries with less number of intersections
        Map<Set<Integer>, Set<Integer>> tailMap = map2.tailMap(entry.getKey(), false);
        for (Map.Entry<Set<Integer>, Set<Integer>> other : tailMap.entrySet())
            // if the intersection set of the current entry contains
            // all intersections from the set of another entry
            if (entry.getKey().containsAll(other.getKey()))
                // then add all intersecting elements of
                // the current entry to another entry
                other.getValue().addAll(entry.getValue());
    }
    
    // final output
    for (Map.Entry<Set<Integer>, Set<Integer>> entry : map2.entrySet())
        System.out.println("Lists: " + entry.getKey()
                + " contain elements: " + entry.getValue());
    

    另见:The intersection of all combinations of n sets

    【讨论】:

      猜你喜欢
      • 2014-11-19
      • 2015-04-05
      • 2013-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-22
      相关资源
      最近更新 更多