c语言中的递归顺序
我已经编写了一个程序,使用回溯方法打印字符串的所有排列c语言中的递归顺序,c,algorithm,recursion,complexity-theory,C,Algorithm,Recursion,Complexity Theory,我已经编写了一个程序,使用回溯方法打印字符串的所有排列 # include <stdio.h> /* Function to swap values at two pointers */ void swap (char *x, char *y) { char temp; temp = *x; *x = *y; *y = temp; } /* Function to print permutations of string This functi
# include <stdio.h>
/* Function to swap values at two pointers */
void swap (char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
/* Function to print permutations of string
This function takes three parameters:
1. String
2. Starting index of the string
3. Ending index of the string. */
void permute(char *a, int i, int n)
{
int j;
if (i == n)
printf("%s\n", a);
else
{
for (j = i; j <= n; j++)
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j)); //backtrack
}
}
}
/* Driver program to test above functions */
int main()
{
char a[] = "ABC";
permute(a, 0, 2);
getchar();
return 0;
}
#包括
/*函数在两个指针处交换值*/
无效交换(字符*x,字符*y)
{
焦炭温度;
温度=*x;
*x=*y;
*y=温度;
}
/*用于打印字符串排列的函数
此函数采用三个参数:
1.一串
2.字符串的起始索引
3.字符串的结束索引*/
无效排列(字符*a,整数i,整数n)
{
int j;
如果(i==n)
printf(“%s\n”,a);
其他的
{
对于(j=i;j复杂度是O(N*N!)
,你有N个置换,你得到了所有置换。
此外,每个排列都需要你打印出来,这是O(N)
-所以在O(N*N!)
我的答案将集中在方法论上,因为这就是明确的问题所在。有关这个特定问题的答案,请参阅其他人的答案,例如amit的答案
当您尝试评估递归算法的复杂性时,您应该像计算迭代算法一样开始计算。但是,当您遇到递归调用时,您还不知道确切的成本是多少。只需将行的成本作为函数写入,并且仍然计算它将要运行的次数
例如(请注意,这段代码很愚蠢,它只是用于示例,没有任何有意义的功能-可以随意编辑并替换为更好的代码,只要它保留了要点):
intf(intn){//将总成本记为C(n)
如果(n==1)返回0;//运行一次,则为常量成本
int i;
int result=0;//运行一次,固定成本
对于(i=0;i而言,通过该程序进行排列的确切数量为(对于长度为N的字符串)
- 启动:N p.启动每个N-1 p.等
- 排列的数量是
N+N(N-1)+N(N-1)(N-2)+……+N(N-1)…(2)
(由于下一个调用刚刚返回,因此以2结尾)
- 或者
N(1+(N-1)(1+(N-2)(1+(N-3)(1+…3(1+2)…))
大概是2N!
在for
循环中添加计数器(删除printf)与公式匹配
- N=3:9
- N=4:40
- N=5:205
- N=6:1236
时间复杂度是O(N!)
有N!
N
元素的排列,因此(j=i+1;j
加排列(a,0,3);
在main()中的复杂度至少是O(N!)
我已经在这里用C#给出了详细的解释。看看这里。没有注意到我可以在这里发表评论,所以在前面的回答中添加了这个链接。@kaitian:ThereO(N!)
确实是排列,但代码也会打印其中的每一个。每一个都是长度N
,因此你需要为每一个排列写一个长度N
,这导致总时间复杂度O(N*N!)
是的,你是对的~~我想说的是,排列的复杂度总是O(N!)虽然C++的STL已经实现了一个非递归版本,叫做NExtPiMutTaln。顺便说一下,N对于N来说非常小!哈哈哈,这似乎不是程序的复杂性。请参见下面的答案。@ Run0:“下面的答案”忽略<代码> Prtff<代码> -没有理由这样做,程序包括它。每个PrTrF都是<代码>(N)
-导致O(N*N!)
运行时。@amit在下面回答-我只是想帮助OP理解是什么。没有理由忽略printf
,它是程序的一部分,每次调用它都是O(N)
.printf是每个置换处理的一个扩展。它是一个线性过程,当N增长时,它不会在接近N!的任何地方自行增长。参见。所以?注意它不是O(N!+N),而是O(N!*N),注意N!*N渐近地大于N!(lim(N->无穷)N!=lim(N->无穷)N=无穷
)根据大O的定义,它意味着N!*N不在O(N!)
中。我确实同意存在N!排列当然,我不同意你可以从分析中“忽略”printf
函数。因此,如果一个算法根据函数f(N)=N*N
它是O(N²)
但是如果它的每个迭代都打印f,那么它就是O(n³)
?我不这么认为。如果它打印长度为O(n)的东西,这取决于它打印的内容
-那么是的。printf是如何工作的?它迭代数组/字符串中的所有字符,并将每个字符打印到屏幕上,因此在算法中有一个函数可以迭代n
更多次。如果函数中的这个循环被调用n^2
次,那么实际上就有n^3
操作。
int f(int n){ //Note total cost as C(n)
if(n==1) return 0; //Runs once, constant cost
int i;
int result = 0; //Runs once, constant cost
for(i=0;i<n;i++){
int j;
result += i; //Runs n times, constant cost
for(j=0;j<n;j++){
result+=i*j; //Runs n^2 times, constant cost
}
}
result+= f(n/2); //Runs once, cost C(n/2)
return result;
}