繁体   English   中英

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

[英]Why time complexity of following code is O(n^2)?

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
        }
}

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

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

你总是从树的根部t开始,每次( i )将等级增加一,直到达到树h的高度。

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

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

print_level接收根节点和要打印的级别。 并且它会递归调用, 直到达到该级别并打印出该级别。
即它循环 i倍(递归调用减小i通过每次一个)。

所以你有1 + 2 + 3 + ... + h次迭代。 由于h = n你得到1 + 2 + 3 ... + n步。 这是(n * (n+1))/2 (高斯和公式),其为O(n^2)

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

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

在这里,我将遵守问题并使用'h'而不是'n'。

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

在此输入图像描述

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM