具有重复字母和连续字母的排列不相同

时间:2013-04-13 07:46:35

标签: c++ algorithm math permutation formula

我一直试图解决关于排列的问题并且没有真正成功。我想生成指定长度的所有排列,以字母开头并以相同结尾,并且没有两个连续的字母应该是相同的。产生的排列可以有重复的字母 例如,
如果数组有{a,b,c,d},我想要所有以a开头和结尾的排列。
答案应该是:
ABCA
阿卜达
ACBA
ACDA
如果数组是{a,b,c,d,e}
输出:
ABCDA
ABADA
abdca

acbda
acada
acdba
acaba
adbca
adaca
adcba
阿达巴
ABCBA
贝巴
ABDBA
ACBCA
ACACA
acdca
ADBDA
adcda
adada

我甚至想知道是否有某种方法可以直接了解我将通过某些公式得到的数字解决方案。
提前谢谢大家..

3 个答案:

答案 0 :(得分:0)

算法如下。你从一些字母a开始,然后有一组你可以使用的所有字母。然后,对于集合中的每个元素,您将展开a到ab ac广告。然后添加一个背面来设置并相应地从每个新单词的集合中删除b,c,d。之后你会做同样的(递归)。唯一棘手的部分是当你完成任务时。然后你还需要删除你开始写的字母,然后再选择倒数第二个字母。

至于数学公式:

我们将T(n,l)表示为长度为l的“排列”数量和大小为n的字母表。 现在我们可以设计以下递归:

T(n,3) = n - 1 // a(something other than a)a
T(n,k) = (n-1)^(l-2) - T(n, k-1)

递归情况会发生什么。我们从考虑最后一个和倒数第二个字母可能相等的情况开始。所以我们有a(letter other than previous, so (n-1) choices)^(l-2),最后我们减去这些情况,其中第一个字母等于倒数第二个,即T(n, k-1)

要在计算机上有效地计算它,请使用动态编程或记忆。

答案 1 :(得分:0)

首先,也许你应该将你的问题分成两部分。一个用于堆栈交换的“数学”部分,一个具有可能性的数量,另一个用于算法的生成。

数学答案:

如果我理解正确,你希望你的字符串开始并以某个字母开头,例如“a”。然后排列的数量取决于生成的数组的大小。对于您描述的问题,您需要将字符串理解为“a * a”,其中“”可以采用多个值。星号可以26种方式填充(字母表中的字母数量)减去与您的规则不相容的字母数量。因此,第一颗星的最大数量为25种(因为你不能在两个连续的字符中重复“a”)。第二颗恒星只能有24种可能性,因为它不能是“a”或之前的字母(26-2 = 24)。然后,当我们组成可能性时,你有25 * 24组合。

使用大小为n个字符的字符串(不包括从头开始设置的第一个和最后一个),你有25 ^(n-1)* 24个组合。

对于算法部分:

请参阅backtracking以获得易于实施且快速生成所需内容的方法。您只需浏览字符串并将那些未知字符(* s)设置为不重复相同字母的值,依此类推,直到您生成所有值。

从问题的方式来看,我认为你的问题是某种功课,所以如果你编写自己的算法而不是使用STL等等会更好。

答案 2 :(得分:-1)

您可以使用STL中的next_permutation算法

#include <iostream>     // std::cout
#include <algorithm>    // std::next_permutation, std::sort

int main () {
char mychars[] = "abc";;

std::sort (mychars,mychars+3);

std::cout << "The 3! possible permutations with 3 elements:\n";
do {
  std::cout << mychars[0] << ' ' << mychars[1] << ' ' << mychars[2] << '\n';
} while ( std::next_permutation(mychars,mychars+3) );

std::cout << "After loop: " << mychars[0] << ' ' << mychars[1] << ' ' << mychars[2] << '\n';

return 0;

参考 - http://www.cplusplus.com/reference/algorithm/next_permutation/ 强文