为什么以下代码的时间复杂度为O(n ^ 2)?

时间:2016-06-25 10:32:29

标签: c++ c time-complexity

void level_order_recursive(struct node *t , int h) //'h' is height of my binary tree
{                                                 //'t' is address of root node
    for(int i = 0 ; i <= h ; i++)  
    {
        print_level(t , i);
    }
} 
  

每次调用print_level()之后,我认为递归函数被称为(2 ^ i)次。所以2 ^ 0 + 2 ^ 1 + 2 ^ 2 .... 2 ^ h应该给出O(2 ^ n)的时间复杂度。我哪里出错?

void print_level(struct node * t , int i)
{
    if( i == 0)
        cout << t -> data <<" ";
    else
        {
            if(t -> left != NULL)
                print_level(t -> left , i - 1);   //recursive call
            if(t -> right != NULL)
                print_level(t -> right , i - 1); //recursive call
        }
}

4 个答案:

答案 0 :(得分:3)

你混淆了h和n。 h是树的高度。 n显然是树中元素的数量。因此print_level采用最坏情况O($ 2 ^ i),但这也只是n。

最糟糕的情况发生在你有一个退化树,每个节点只有一个后继。在这种情况下,您有n个节点,但树的高度也是h = n。在这种情况下,每次调用print_level都需要i步,并且将i从1加到h = n得到O($ n ^ 2)。

答案 1 :(得分:2)

您始终从树t的根开始,每次将等级提高一(i),直到达到树h的高度。

你说它是一棵二叉树,但你没有提到任何属性,例如平衡左右。所以我假设它可以是一个不平衡的二叉树,因此在最坏的情况下树的高度可以是h = n,其中n是节点的数量(这是一个完全不平衡的树,看起来像一个列表实际上)。

这意味着level_order_recursive循环n次。即最糟糕的情况是树有n级别。

print_level接收根节点和要打印的级别。它以递归方式调用直到达到级别并打印出该级别。
即I。它循环 i次(递归调用每次减少i)。

所以你有1 + 2 + 3 + ... + h次迭代。自h = n以来,您获得了1 + 2 + 3 ... + n步骤。这是(n * (n+1))/2(高斯和公式),它位于O(n^2)

如果你可以确保树是平衡的,那么你会改善最坏的情况,因为高度为h = ld(n),其中 ld 表示二进制对数。

答案 2 :(得分:2)

基于thisthat,第3页和第4页,二分搜索算法(类似于我们的情况)的时间复杂度为T(n) = T(n/2) + c。 除此之外,浏览左侧和右侧子树,因此下面的公式中的2T(n / 2),因为这是一个遍历算法,而不是搜索算法。

在这里,我将遵守问题并使用&#39; h&#39;而不是&#39; n&#39;。

使用递归关系,您将获得以下证明:

enter image description here

答案 3 :(得分:1)

在最坏的情况下,时间复杂度将是O(n ^ 2)但不能是2 ^ n,因为每个级别的时间复杂度将是 - > O(n)+ O(n-1)+ O(n-2)+ ... + O(1)最差O(n ^ 2)。