简体   繁体   中英

Print all partitions into disjoint combinations of fixed size

I have an array of numbers from 1 to n, and I need to find all possible partitions into disjoint combinations of 3 numbers.

That is, for n = 9 the situation is as follows:

Array: 1, 2, 3, 4, 5, 6, 7, 8, 9;

Possible combinations of 3: 123, 124... 245, 246... 478, 479, etc.;

Possible partitions into 3 disjoint combinations: 123 456 789, 123 457 689... 123 468 579... 127 458 369, etc.

I've found an algorithm for finding combinations of 3 numbers from a set, here it is: https://www.geeksforgeeks.org/print-all-possible-combinations-of-r-elements-in-a-given-array-of-size-n / (there are even 2 of them, but I used the first one). Now the question is how to find combinations of the combinations themselves, and this already causes difficulties: it seems to me that for this I need to deal with recursion again, but how and where exactly to use it, I don't fully understand (and perhaps the point is then another). Also I've seen a non-recursive algorithm that finds all the combinations from given numbers, https://rosettacode.org/wiki/Combinations#C.23 , but could do nothing with it (I enclose my work with it). Could you please help me?

public static IEnumerable<int[]> Combinations(int[] a, int n, int m)
        {
            int[] result = new int[m];
            Stack<int> stack = new Stack<int>();
            stack.Push(0);
            while (stack.Count > 0)
            {
                int index = stack.Count - 1;
                int value = stack.Pop();
                while (value < n)
                {
                    result[index++] = ++value;
                    stack.Push(value);
                    if (index == m)
                    {
                        for (int i = 0; i < 3; i++)
                        {
                            a = a.Where(val => val != result[i]).ToArray();
                        }
                        return Combinations (a, n-3, m);
                        break;
                    }
                }
            }
        }

Assuming n is a multiple of 3, the recursive algorithm is pretty simple. (Writing it efficiently is a bit more of a challenge:-) ).

In pseudocode, generalising 3 to k:

# A must have a multiple of k elements
# I write  V \ C to mean "V without the values in C". Since producing
# copies is expensive, you should find a more efficient way of doing
# this.
Partition(A, k):
    If A has k elements, produce the partition consisting only of A
    Otherwise:
        Let m be the smallest element of A. 
        For each combination C of k-1 elements from A \ [m]:
            Add m to C
            For each partition P generated by Partition(A \ C, k):
                produce P with the addition of C

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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