如何查找多集的所有分区(允许重复的集)

时间:2018-12-05 05:33:18

标签: algorithm set combinations partitioning

给出一个可能包含重复项的数字集合,找到它的所有分区。 (划分集合的所有可能方法。)

例如,多集{1,1,2}有4个分区:

分区1 = {{1},{1},{2}}    分区2 = {{1},{1,2}}    分区3 = {{1,1},{2}}    分区4 = {{1,1,2}}

这里是一个类似的问题How to find all partitions of a set,但在该问题中,所有数字都是不同的。

集合分区的定义:https://en.wikipedia.org/wiki/Partition_of_a_set

多集定义:https://en.wikipedia.org/wiki/Multiset

以任何常见编程语言编写的解决方案,带有一些解释,将不胜感激。


更新:

似乎很多人都对问题的所在感到困惑。 询问给定集合的所有可能子集。而是要求您找出划分给定数字集合的所有不同方法。

2 个答案:

答案 0 :(得分:1)

嘿,我确实有python解决方案:

from sympy.utilities.iterables import multiset_partitions
from pi in multiset_partitions([1,1,3]):
    print pi

查看代码,您可以在Knuth的AOCP中找到算法,就在这里:http://www.cs.utsa.edu/~wagner/knuth/fasc3b.pdf

算法M,第39/40页。

干杯:)

答案 1 :(得分:-2)

这是一个 分区集 问题。

  

原始集中的元素数始终等于每个分区中的元素数之和。

可以使用 backtracking 递归来解决。此C ++程序可能会有用。

void solve (set<vector<vector<int>>>& solution, vector<int> inputSet, 
vector<vector<int>>& partitions, vector<int> partition, int n, int i) {
    int numberOfElements = 0;
    for (int i=0; i<partitions.size(); i++) {
        numberOfElements += partitions[i].size();
    }
    if (numberOfElements == n) {
        vector<vector<int>> newPartitions = partitions;
        for (int i=0; i<newPartitions.size(); i++) {
            sort (newPartitions[i].begin(), newPartitions[i].end());
        }
        sort(newPartitions.begin(), newPartitions.end());
        solution.insert(newPartitions);
        return;  
    }
    for (int j=i; j<n; j++) {
        partition.push_back(inputSet[j]);
        partitions.push_back(partition);
        vector<int> partitionNew;
        solve(solution, inputSet, partitions, partitionNew, n, j+1);
        partitions.pop_back();
    }
}

void permute (set<vector<vector<int>>>& solution, vector<int>& inputSet, int i, int n) {
    if (i == n) {
        vector<int> partition;
        vector<vector<int>> partitions;
        solve(solution, inputSet, partitions, partition, inputSet.size(), 0);
        return;
    }
    for (int j=i; j<=n; j++) {
        swap(inputSet[i], inputSet[j]);
        permute(solution, inputSet, i+1, n);
        swap(inputSet[i], inputSet[j]);
    }
}

这是工作示例:Generate all Partitions

编辑:我误解了问题。我已经更新了答案。现在,它将生成所有可能的分区。