给出一个可能包含重复项的数字集合,找到它的所有分区。 (划分集合的所有可能方法。)
例如,多集{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
以任何常见编程语言编写的解决方案,带有一些解释,将不胜感激。
更新:
似乎很多人都对问题的所在感到困惑。 不询问给定集合的所有可能子集。而是要求您找出划分给定数字集合的所有不同方法。
答案 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
编辑:我误解了问题。我已经更新了答案。现在,它将生成所有可能的分区。