我在这里看过各种帖子,它们计算二叉树的直径。可以找到一个这样的解决方案here(查看已接受的解决方案,而不是问题中突出显示的代码)。
我很困惑为什么代码的时间复杂度为O(n ^ 2)。我没有看到如何遍历树的节点两次(一次用于高度(通过getHeight()
)和一次用于直径(通过getDiameter()
)将是n ^ 2而不是n + n是2n。任何帮助将不胜感激。
答案 0 :(得分:1)
正如您所提到的,getHeight()
的时间复杂度为O(n)
。
对于每个节点,调用函数getHeight()
。因此,单个节点的复杂性为O(n)
。因此,整个算法(对于所有节点)的复杂性为O(n*n)
。
答案 1 :(得分:1)
计算每个节点的每个子树的高度应该是O(N),你只需要使用有序遍历遍历树一次。
int treeHeight(root)
{
if(root == null) return -1;
root->height = max(treeHeight(root->rChild),treeHeight(root->lChild)) + 1;
return root->height;
}
这将访问每个节点1次,因此订单为O(N)。
将此与来自链接源的结果相结合,您将能够确定哪个2个节点在最差的另一次遍历之间具有最长的路径。
确实this描述了在O(N)
中执行此操作的方法此解决方案(优化的解决方案)与引用的解决方案之间的区别在于,在将搜索大小缩小到仅1个节点(根节点)之后,每次引用的解决方案都会重新计算树高。因此,从上面来看,复杂性将是O(N +(N-1)+ ... + 1)。
总和
1 + 2 + ... + N
等于
= N(N + 1)/2
因此,重复调用getHeight所有操作之和的复杂性将为O(N ^ 2)
为了完整起见,相反,优化后的解决方案getHeight()在预计算之后将具有复杂度O(1),因为每个节点都将该值存储为节点的数据成员。
答案 2 :(得分:0)
可以预先计算所有子树高度(使用O(n)时间),因此找到直径的总时间复杂度将为O(n)。