如何从列表中获取不同的分组组合

时间:2017-03-20 18:15:41

标签: java recursion grouping combinations

我正在研究一个问题,我希望将列表分组为两个并获得所有可能的组合。 例如:对于list [A,B,C,D]; 我正在尝试创建一个能给我ff的方法:

   A and BCD
    B and ACD
    C and ABD
    D and ABC
    AB and CD
    AC and BD
    AD and BC

etc...

我知道递归是答案,但我不知道从哪里开始。有人能指出我正确的方向吗?

到目前为止我的尝试:

List<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("D");

    for (int x = 1; x < list.size() - 1; x++) {  //how many elements in one group
        for (int i = 0; i < list.size(); i++) {   //get first group..
            List<Integer> chosenIndices = new ArrayList<>();   //?..
            chosenIndices.add(i); // good for one element grouping only.. 
            List<String> firstGroup = getFirstGroup(list, chosenIndices); //method to pick chosenindices
            List<String> secondGroup = getRestofList(list, chosenIndices);  //method to exclude chosenIndices
            System.out.println(firstGroup + ": " + secondGroup);
        }

    }

这会处理第一组包含一个元素的组合,但我无法弄清楚如何获得下一次迭代并为第一组提供两个元素的列表。 我希望这是有道理的。

1 个答案:

答案 0 :(得分:0)

我的第一个答案可能很有用,但效果不好。遗憾。

这是另一个例子。它基于组合学规则:

(n, k) = (n - 1, k - 1) + (n - 1, k)

其中n - 是元素总数,k是元素数是组

@Test
    public void test() throws Exception {
        List<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("D");

        List<String> result = new ArrayList<>();

        for (int i = 1; i < list.size() + 1; i++) {
            combine(list, result, i);
        }

        System.out.println(result);
    }

    public static void combine(List<String> list, List<String> result, int k) {
        if (k > list.size())
            return;

        // calculate and print the possible combinations
        // e.g. c(4,2)
        int ncr = fact(list.size()) / fact(list.size() - k) / fact(k);
        System.out.println(String.format("C(%s, %s). Combinations nbr = %s", list.size(), k, ncr));

        // get the combine by index
        // e.g. 01 --> AB , 23 --> CD
        int combination[] = new int[k];

        // position of current index
        int r = 0;
        int index = 0;

        while (r >= 0) {
            // for r = 0 ==> index < (4+ (0 - 2)) = 2
            if (index <= (list.size() + (r - k))) {
                combination[r] = index;

                // if we are at the last position print and increase the index
                if (r == k - 1) {
                    //do something with the combine e.g. add to list or print
                    add(combination, list, result);
                    index++;
                } else {
                    // select index for next position
                    index = combination[r] + 1;
                    r++;
                }
            } else {
                r--;
                if (r > 0)
                    index = combination[r] + 1;
                else
                    index = combination[0] + 1;
            }
        }
    }

    private static int fact(int n) {
        if (n == 0)
            return 1;
        else
            return n * fact(n - 1);
    }

    private static void add(int[] combination, List<String> elements, List<String> result) {
        String output = "";
        for (int i = 0; i < combination.length; i++) {
            output += elements.get(combination[i]);
        }

        result.add(output);
    }

输出将是:

C(4, 1). Combinations nbr = 4
C(4, 2). Combinations nbr = 6
C(4, 3). Combinations nbr = 4
C(4, 4). Combinations nbr = 1
[A, B, C, D, AB, AC, AD, BC, BD, CD, ABC, ABD, ACD, BCD, ABCD]