简体   繁体   English

将所有分区打印成固定大小的不相交组合

[英]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.我有一个从 1 到 n 的数字数组,我需要找到所有可能的分区为 3 个数字的不相交组合。

That is, for n = 9 the situation is as follows:也就是说,对于 n = 9,情况如下:

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

Possible combinations of 3: 123, 124... 245, 246... 478, 479, etc.; 3种可能的组合:123、124...245、246...478、479等;

Possible partitions into 3 disjoint combinations: 123 456 789, 123 457 689... 123 468 579... 127 458 369, etc.可能的分区为 3 个不相交的组合:123 456 789、123 457 689... 123 468 579... 127 458 369 等。

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).我找到了一种从一组中查找 3 个数字组合的算法,这里是: https://www.geeksforgeeks.org/print-all-possible-combinations-of-r-elements-in-a-given- array-of-size-n / (甚至有 2 个,但我使用了第一个)。 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).此外,我还看到了一种非递归算法,它可以从给定的数字https://rosettacode.org/wiki/Combinations#C.23中找到所有组合,但对它无能为力(我附上我的工作)。 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.假设n是 3 的倍数,递归算法非常简单。 (Writing it efficiently is a bit more of a challenge:-) ). (有效地编写它是一个挑战:-))。

In pseudocode, generalising 3 to k:在伪代码中,将 3 推广到 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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