C 查找给定字符串的所有可能排列

C 查找给定字符串的所有可能排列,c,algorithm,C,Algorithm,这只是为了解决一个看起来很有趣的问题。我想了想,但没能在有效的时间内找到解决这个问题的方法。也许我的观念还在建立。。。无论如何,问题如下 想要找出给定字符串的所有可能排列。。。。。。。另外,如果这个问题有任何可能的变化,请分享 我在网上找到了一个使用递归的解决方案。。但这并不令人满意,因为它看起来有点错误 计划如下:- void permute(char s[], int d) { int i; if(d == strlen(s)) printf("%s",s);

这只是为了解决一个看起来很有趣的问题。我想了想,但没能在有效的时间内找到解决这个问题的方法。也许我的观念还在建立。。。无论如何,问题如下

想要找出给定字符串的所有可能排列。。。。。。。另外,如果这个问题有任何可能的变化,请分享

我在网上找到了一个使用递归的解决方案。。但这并不令人满意,因为它看起来有点错误

计划如下:-

void permute(char s[], int d)
{
   int i;

   if(d == strlen(s))
      printf("%s",s);

   else
   {
      for(i=d;i<strlen(s);i++)
      {
         swap(s[d],s[i]);
         permute(s,d+1);
         swap(s[d],s[i]);
      }
   }
}
void排列(字符s[],int d)
{
int i;
如果(d==strlen)
printf(“%s”,s);
其他的
{

对于(i=d;i来说,代码看起来是正确的,尽管您只有算法的核心,而不是一个完整的程序。您必须提供缺少的位:头、一个
main
函数和一个
swap
宏(您可以将
swap
作为
swap(s,d,i)
调用,使之成为一个函数)

为了理解该算法,最好在
permute
函数的开头添加一些跟踪输出,例如
printf(“permute(%s,%d)”,s,d)
,并使用3或4个字符的字符串运行程序

基本原理是,对
permute
的每次递归调用都会将每个剩余元素依次放置在
d
位置;位于
d
位置的元素通过将其放置在上述剩余元素所在的位置来保存(即,交换元素)。对于每个位置,
permute
被递归调用,以在位置
d
之后生成所有所需的子字符串。因此,对
permute
的顶级调用(
d
=0)将连续尝试位置0中的所有元素,第二级调用(
d
=1)尝试位置1中的所有元素,但已处于位置0的元素除外,以此类推。下一个最深的调用(
d
=
n
-1)在最后一个位置有一个元素要尝试,最深的调用(
d
=
n
)打印结果排列


核心算法需要Θ(n·n!)运行时间,这是可能的最佳时间,因为这是输出的大小。然而,这种实现的效率较低,因为它在每次迭代时重新计算
strlen(s)
,以获得Θ(n²·n!)运行时间;预先计算长度的简单修正将产生Θ(n·n!)实现需要Θ(n)内存,这是最好的,因为这是输入的大小。

有关递归的解释,请参阅Gilles答案

您的代码有一些问题。首先,在C中很难将所需的
交换
作为函数实现,因为C缺乏引用调用的概念。您可以尝试使用宏来实现这一点,但是您必须使用异或技巧就地交换值,或者使用临时变量


然后,在每个递归级别上重复使用
strlen
会增加程序的复杂性。正如您所说的,这是在每个递归级别的每次迭代中完成的。因为字符串甚至会发生变化(因为
交换
s)编译器甚至无法注意到这始终是相同的。因此,他无法优化任何内容。如果您这样实现,搜索字符串中终止的
'\0'
,到目前为止将主导所有其他指令。

这不是按定义在n!时间内运行吗?不,这不是
n!
:(1)
n×n!
对于递归的每个叶中的
printf
,以及(2)对于每个递归级别上重复的
strlen
,大致
n²×n!
。您可以很容易地去掉(2)中的额外
n
因子通过更仔细地编程。您的复杂性观察结果并不完全正确。在给出的实现形式中,它是
Θ(n²×n!)
,因为在每个递归级别上都有愚蠢的
strlen