一些固定数字的排列
Posted
技术标签:
【中文标题】一些固定数字的排列【英文标题】:Permutations with some fixed numbers 【发布时间】:2011-01-19 21:07:07 【问题描述】:如果我在指定位置需要一些字符/数字,如何有效地生成数字(或单词中的字符)的排列?
例如生成所有数字,其中 digit 3 位于第二个位置,digit 1 位于第二个位置。数字中的每个数字都必须是唯一的,并且您只能从数字 1-5 中进行选择。
4 3 2 1 5
4 3 5 1 2
2 3 4 1 5
2 3 5 1 4
5 3 2 1 4
5 3 4 1 2
我知道有一个 next_permutation 函数,所以我可以准备一个带有数字 4, 2, 5 的数组并将其循环发布到该函数,但是如何处理固定位置?
【问题讨论】:
【参考方案1】:生成2 4 5
的所有排列,并在输出例程中插入 3 和 1。只要记住他们必须的位置:
int perm[3] = 2, 4, 5;
const int N = sizeof(perm) / sizeof(int);
std::map<int,int> fixed; // note: zero-indexed
fixed[1] = 3;
fixed[3] = 1;
do
for (int i=0, j=0; i<5; i++)
if (fixed.find(i) != fixed.end())
std::cout << " " << fixed[i];
else
std::cout << " " << perm[j++];
std::cout << std::endl;
while (std::next_permutation(perm, perm + N));
输出
2 3 4 1 5
2 3 5 1 4
4 3 2 1 5
4 3 5 1 2
5 3 2 1 4
5 3 4 1 2
【讨论】:
所以我应该创建下一个数组 0, 2, 4 并在将生成的排列放回数字时使用它? 只需将2,4,5
放入数组中即可。我已经发布了示例代码。 (很好的练习;)【参考方案2】:
我已经阅读了其他答案,我相信对于您的具体问题,它们比我的要好。但是,如果有人需要通用解决方案来解决您的问题,我会回答。
我最近需要生成 3 个独立的连续范围 [first1, last1) + [first2, last2) + [first3, last3) 的所有排列。这对应于您的情况,所有三个范围的长度均为 1,并且仅由 1 个元素分隔。就我而言,唯一的限制是 distance(first3, last3) >= distance(first1, last1) + distance(first2, last2) (我确信可以通过更多的计算费用来放松)。
我的应用程序是生成每个唯一的排列,但不是它的反转。代码在这里:
http://howardhinnant.github.io/combinations.html
具体适用的函数是 combine_discontinuous3(创建组合),它在 reversible_permutation::operator() 中的使用创建排列。
这不是针对您的问题的现成打包解决方案。但它是一个工具集,可用于解决您的问题的概括。同样,对于您的确切简单问题,我推荐其他人已经提供的更简单的解决方案。
【讨论】:
【参考方案3】:记住在哪些地方需要固定号码。从阵列中删除它们。 像往常一样生成排列。每次排列后,将您的固定数字插入它们应该出现的位置,然后输出。
【讨论】:
【参考方案4】:如果您有一组数字 4,3,2,1,5 并且您知道 3 和 1 不会被置换,那么您可以将它们从集合中取出并生成 4 的幂集, 2, 5。之后,您只需将 1 和 3 插入到电源组中每个组的各自位置即可。
我发布了similar question,您可以在其中看到 powerset 的代码。
【讨论】:
生成 powerset 需要指数级的内存。使用标准 C++ 函数next_permutation
,这可以通过恒定数量的额外内存来完成。
@larsmans,我在这里有点困惑......我简要查找了question in which the powerset is generated using next_permutation,运行时间似乎是:O(n! *2^n)。 Generating a powerset takes O(n*2^n),所以看起来你要么节省运行时间,要么节省内存。
首先,OP 的问题是生成所有 permutations,而不是 subsets 或 combinations,因此 powerset 是在这里没用。接下来,生成所有排列的时间复杂度由排列数限制,即 n! = O(n ^ n)。使用next_permutation
循环对于时间复杂度n 的问题来说是最佳的! * O(n) = O(n ^ (n + 1)) = O(n ^ n) 和常数空间。以上是关于一些固定数字的排列的主要内容,如果未能解决你的问题,请参考以下文章