Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 这个递归函数的时间复杂度是多少? void solve(字符串op,int n,int零,int一) { 如果(n==0){ 如果我理解正确,函数的时间复杂度是O(N*2^N)。我使用递归树来分析结果。_C++_Recursion - Fatal编程技术网

C++ 这个递归函数的时间复杂度是多少? void solve(字符串op,int n,int零,int一) { 如果(n==0){ 如果我理解正确,函数的时间复杂度是O(N*2^N)。我使用递归树来分析结果。

C++ 这个递归函数的时间复杂度是多少? void solve(字符串op,int n,int零,int一) { 如果(n==0){ 如果我理解正确,函数的时间复杂度是O(N*2^N)。我使用递归树来分析结果。,c++,recursion,C++,Recursion,因此,我们想在这里估计最坏的情况。最坏的情况是如果条件(1>0)总是返回true。是否可能?是的,如果1-0>=n。由于我不知道任务的上下文,我可以假设它 T(n)是函数的复杂度。函数用(n-1)调用自身两次。这意味着 void solve(string op, int n, int zeros, int ones) { if(n==0){ cout<<op<<" "; return; } str

因此,我们想在这里估计最坏的情况。最坏的情况是如果条件(1>0)总是返回true。是否可能?是的,如果1-0>=n。由于我不知道任务的上下文,我可以假设它

T(n)是函数的复杂度。函数用(n-1)调用自身两次。这意味着

void solve(string op, int n, int zeros, int ones)
{
    if(n==0){
        cout<<op<<" ";
        return;
    }
    string op1 = op;
    op1.push_back('1');
    solve(op1, n-1, zeros, ones+1);
    if(ones > zeros){
        string op2 = op;
        op2.push_back('0');
        solve(op2, n-1, zeros+1, ones);
        return;
    }

}

T(n) = 2T(n-1) + c =
     = 2(2T(n-2) + c) + c = 4T(n-2) + 3c = 
     = 4(2T(n-3) + c) + 3c = 8T(n-3) + 7c = 
     = ...
     = 2^k*T(n-k) + (2^k-1)*c
其中c是一个常量,用于您正在执行的其他例程,如追加“1”或“0”、条件求值等。什么不依赖于n

所以

因此,如果(n-k)==0,你就完成了,因为T(0)=z。那么,当k==n时我们就完成了。关于z,这并不明显。在当前的实现中,我们确实输出了一个字符串,它是O(n)。如果我们只计算字符串,它将是O(1)。如果我们打印是必要的,那么最终的复杂性将是O(n2^n),如果不是,则是O(2^n)

也就是说

void solve(string op, int n, int zeros, int ones)
{
    if(n==0){
        cout<<op<<" ";
        return;
    }
    string op1 = op;
    op1.push_back('1');
    solve(op1, n-1, zeros, ones+1);
    if(ones > zeros){
        string op2 = op;
        op2.push_back('0');
        solve(op2, n-1, zeros+1, ones);
        return;
    }

}

T(n) = 2T(n-1) + c =
     = 2(2T(n-2) + c) + c = 4T(n-2) + 3c = 
     = 4(2T(n-3) + c) + 3c = 8T(n-3) + 7c = 
     = ...
     = 2^k*T(n-k) + (2^k-1)*c
[更新1]

在意识到真正的问题后,从代码片段中看不清楚,但在从提供的链接中读取信息后变得清楚,我想说复杂性是不同的

在作出假设的情况下,上述计算仍然正确

现在,对于这个问题,我们想找到长度为n的1和0的所有序列,其中每个前缀包含不小于该前缀中0个数的1

该算法为这个问题提供了解决方案。正如您在每次递归调用时所注意到的,该算法将0或1添加到结果序列中。这意味着递归调用的数量正好是结果字符串中的符号数

我们知道每个得到的字符串的长度是n。所以,我们需要找出字符串的数目。让我们看看你的程序对于不同的n的查找:

T(n) = z*2^n + (2^n - 1)*c = O(z2^n)
因此,如果你仔细观察,你会发现这些是二项式系数
C(n,n/2)
。这个二项式系数可以大致估计为
~2^n/(\pi*n/2)
。因此,算法的复杂度是
O(2^n/(n))但是,如果我们还考虑在递归结束时打印,则需要用n乘法,因为它是输出字符串的长度。因此,我们得到O(2 ^ n)

。 为了清楚起见,我们需要证明我们的假设是正确的。希望你能通过归纳法或其他方法做到这一点

[更新2]

您的实现在每次迭代时都会遇到处理字符串的问题。这会通过因子n降低执行速度。您可以通过传递对字符串的引用并在递归调用后删除添加的字符来避免这种情况,如下所示:

n    | number of strings 
-----------------------
1    |    1
2    |    2
3    |    3
4    |    6
5    |    10
6    |    20
7    |    35
8    |    70
void solve(字符串&op,整数n,整数零,整数一)
{
如果(n==0){

你可以计算一下这个函数被调用的频率,以及在每个(2-多个基/递归)情况下完成了多少工作。答案很好,但这也让我很好奇,你说你不知道上下文,但这个问题也有一个特定任务的链接(我假设要解决这个任务,我们首先必须用solve(“,4,0,0”);调用函数,但是函数的行为是确定的。在这种情况下,谈论最坏情况或者大O符号是否相关?即使在这种情况下,我们只知道从solve(“,n,0,0)开始。我们可以根据这一点对我们的估计进行优化吗?
c
是我们不关心的常数的假设是不正确的。字符串是复制的,它的长度取决于参数。@AlexR:我没有说我们不应该关心
c
。事实上这是计算的一部分。你对co的评论ping字符串是正确的。它确实取决于
n
,但是可以通过传递对字符串的引用而不是复制字符串,以及在递归调用之后删除添加的字符来避免这种情况。@SpyrosMourelatos:没有注意到链接。它从一开始就存在吗?我一大早就阅读了问题,然后打开了窗口打开了一段时间。几个小时后,我写了答案而没有更新页面。但是我可能错过了。抱歉。如果链接中描述的上下文,则是不同的。我已经更新了我的答案。@ Alxr Hum……好吧,打印确实不是免费的。事实上,我不认为它是ALGO的一部分。我们可以。数一数这样的序列。算法步骤是一样的。但是你是对的。我会相应地更新。你能解释一下它的O(N*2^N)吗?