[英]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.