如果我需要在指定地点使用某个字符/数字,如何有效地生成数字的排列(或单词中的字符)?
e.g。从头开始在第二位生成数字3 的所有数字,在数字末尾的第二位生成数字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}的数组并将其循环发布到此函数,但是如何处理固定位置?
答案 0 :(得分:6)
生成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
答案 1 :(得分:1)
我已经阅读了其他答案,我相信他们比你的具体问题更好。但是,我正在回答,以防有人需要一个通用的解决方案来解决你的问题。
我最近需要生成3个独立连续范围[first1,last1] + [first2,last2)+ [first3,last3]的所有排列。这与您的情况相对应,所有三个范围的长度均为1,并且仅由1个元素分隔。在我的情况下,唯一的限制是距离(first3,last3)&gt; =距离(first1,last1)+距离(first2,last2)(我肯定可以放松更多的计算费用)。
我的应用是生成每个独特的排列而不是它的反转。代码在这里:
http://howardhinnant.github.io/combinations.html
具体适用的函数是combine_discontinuous3(创建组合),以及它在reversible_permutation :: operator()中的使用,它创建了排列。
这不是针对您的问题的现成的打包解决方案。但它是一个可用于解决问题概括的工具集。同样,对于您确切的简单问题,我建议其他人提供的更简单的解决方案。
答案 2 :(得分:0)
请记住您想要固定号码的地方。从阵列中删除它们。 像往常一样生成排列。每次排列后,将固定数字插入它们应出现的位置,然后输出。
答案 3 :(得分:0)
如果您有一组数字{4,3,2,1,5},并且您知道3和1不会被置换,那么您可以将它们从集合中取出并为{4生成一个powerset ,2,5}。之后你要做的就是在功率组中为每组设置插入1和3各自的位置。
我发布了similar question,在那里你可以看到powerset的代码。