[英]What is the time complexity of printing all paths of a BST
我有这段代码,它与本网站上具有相同问题的其他一些代码略有不同:
public void printAllRootToLeafPaths(Node node,ArrayList path) {
if(node==null){
return;
}
path.add(node.data);
if(node.left==null && node.right==null)
{
System.out.println(path);
return;
}
else {
printAllRootToLeafPaths(node.left, new ArrayList(path));
printAllRootToLeafPaths(node.right,new ArrayList(path));
}
}
有人可以解释为什么最好的情况是 O(nlogn) 吗? 最坏的情况,树分解成一个链表,数组被复制 1+2+3+...+n-1+n 次,相当于 n^2,所以时间复杂度是 O(n^2) .
沿着路径中的每个节点复制最佳情况数组。 所以复制它看起来像 1+2+3+...+logn。 N/2 次。 那么,如果 1+2+3+...+n-1+n 是 n^2,为什么总和 (logn)^2 不是呢? 制作最佳情况 O(n(logn)^2)?
是的,所有的复制都需要考虑在内。
这些副本不是必需的; 编写以下函数很容易:
对于非复制算法,算法的成本是打印路径的成本,它是从根到叶的所有路径长度的总和。 在每次调用时复制数组,使成本成为从根到每个节点的路径之和,而不是每个叶子。 (数组被复制两次的事实实际上与复杂度分析无关;它只是意味着乘以一个常数因子,可以忽略。)
使用非复制算法,最好的情况是一棵线性树,每个节点只有一个孩子。 那么只有一个路径长度为N的叶子,所以总成本是 O( N )。 但如果你在每个节点上复制,那是最坏的输入; 节点路径长度是连续整数,节点路径长度之和是二次的。
对于您的算法,最好的情况是完全平衡的完全占用树。 在完全占用的树中,叶子节点比非叶子节点多一个; 换句话说,大约一半的节点是叶子。 在完美平衡的树中,每个节点都可以在最多 log N步内从根到达。 所以到每个节点的路径长度之和是 O( N log N )。 (有些节点更接近,但是对于计算大 O,我们可以忽略这个事实。即使我们将其考虑在内,我们也会发现它不会改变渐近行为,因为每个深度的节点数每个连续级别的级别加倍。)因为一半的节点是叶子,所以这个输入的成本是 O( N log N ) 与非复制算法也是如此。
两种算法都表现出最坏情况的二次复杂度。 我们已经看到了复制算法的最坏情况输入:只有一个叶子的线性树。 对于非复制算法,我们使用非常相似的东西:由左链接主干组成的树,其中每个右链接都是叶子:
root
/\
/ \
/\ 7
/ \
/\ 6
/ \
/\ 5
/ \
/\ 4
/ \
/\ 3
/ \
1 2
由于那棵树被完全占用,它的一半节点是叶子,并且它们的距离连续增加,所以这又是二次的(尽管常数乘数更小。)
我认为您错过了将整个数组复制到新数组的时间复杂度。
在根节点: one element is added, but 2 new arrays are created
。
在根节点的左子节点: one element is added, but 2 new arrays are created with 2 elements
。
. . .
最后只有一层: one element is added, but 2 new arrays are created of size log n to base 2.
在最后一级:添加一个元素,并打印 log n 个元素。
因此,在每个节点处,有一个将元素添加到列表的操作,以及一个打印或复制大小列表 (log h) 的操作 - 其中 h 是树中节点的高度。
由于我们只遍历所有元素一次,因此操作总数为: n additions + Sum (log h1 + log h2 + log h3 +.... log hn)
其中 h1, h2, h3...hn 是每个节点的高度。
大约是n + O(n log n)
~
O(n log n)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.