例如,如果输入字符串为“ABC”,则输出应为“ABC,ACB,BAC,BCA,CAB,CBA”。
这是我的方法:
#include<stdio.h>
#include<conio.h>
#include<string.h>
void print(char str[],int visited[],int index,char temp[],int len)
{
if(index==len)
{
temp[index]='\0';
printf("\n%s",temp);
return;
}
for(int i=0;i<len;i++)
{
if(!visited[str[i]-'A'])
{
visited[str[i]-'A']=1;
temp[index]=str[i];
print(str,visited,index+1,temp,len);
visited[str[i]-'A']=0;
}
}
}
int main()
{
int visited[20]={0};
char temp[20];
char str[] = "ABCD";
int len=strlen(str);
print(str,visited,0,temp,len);
getch();
return 0;
}
我使用了一个访问过的数组来避免重复字符。 这段代码的复杂性是什么?
答案 0 :(得分:3)
如果你让n是可用的字符总数而k是未选择的字符数,那么你可以看到每个函数调用都做Θ(n)工作(通过遍历长度为{{的数组) 1}}或打印出长度为len
的字符串,然后生成k个递归调用。每次通话完成的总工作总是Θ(n),因此我们可以通过查看总呼叫数来计算完成的总工作量。
请注意,会有
因此总和的次数由总和
给出从k = 0到n(n!/ k!)的总和
= n! (从k = 0到n(1 / k!)的总和)
一个有趣的观察结果是,这里的求和是e(1/0!+ 1/1!+ 1/2!+ 1/3!+ ...)的泰勒展开,稍微缩短了一点。因此,随着n变大,渐进的调用次数接近e n!。它也受n!的下限,所以这个总和是Θ(n!)。由于您每次调用都完成了Θ(n)工作,因此完成的工作总量为Θ(n·n!)。
希望这有帮助!
答案 1 :(得分:1)
根据字符串的长度运行代码并列出print()
次调用的次数,我有:
n=1 calls=2
n=2 calls=5
n=3 calls=16
n=4 calls=65
n=5 calls=326
n=6 calls=1957
n=7 calls=13700
n=8 calls=109601
n=9 calls=986410
n=10 calls=9864101
n=11 calls=108505112
看起来像“e * n!”。