子节点随父节点高度改变_完全二叉树的子节点数
如果讓你數(shù)一下一棵普通二叉樹有多少個節(jié)點,這很簡單,只要在二叉樹的遍歷框架上加一點代碼就行了。
但是,如果給你一棵完全二叉樹,讓你計算它的節(jié)點個數(shù),你會不會?算法的時間復(fù)雜度是多少?
這個算法的時間復(fù)雜度應(yīng)該是 O(logN*logN),如果你心中的算法沒有達(dá)到這么高效,那么本文就是給你寫的。先來看一下python 代碼實現(xiàn):
# 完全二叉子節(jié)點數(shù) class Solution:def countNodes(self, root: TreeNode) -> int:rightdepth, left_n, right_n = 0, root, rootwhile right_n:right_n = right_n.rightleft_n = left_n.leftrightdepth += 1if not left_n:return 2**rightdepth-1return self.countNodes(root.left)+self.countNodes(root.right)+1首先要明確一下兩個關(guān)于二叉樹的名詞「完全二叉樹」和「滿二叉樹」。
我們說的完全二叉樹如下圖,每一層都是緊湊靠左排列的:
我們說的滿二叉樹如下圖,是一種特殊的完全二叉樹,每層都是是滿的,像一個穩(wěn)定的三角形:
如果是一個普通二叉樹,顯然只要向下面這樣遍歷一邊即可,時間復(fù)雜度 O(N):
public int countNodes(TreeNode root) {if (root == null) return 0;return 1 + countNodes(root.left) + countNodes(root.right); }def countNodes(self, root: TreeNode) -> int:if not root:return 0return self.countNodes(root.left)+self.countNodes(root.right)+1那如果是一棵滿二叉樹,節(jié)點總數(shù)就和樹的高度呈指數(shù)關(guān)系,時間復(fù)雜度 O(logN):
public int countNodes(TreeNode root) {int h = 0;// 計算樹的高度while (root != null) {root = root.left;h++;}// 節(jié)點總數(shù)就是 2^h - 1return (int)Math.pow(2, h) - 1; }完全二叉樹比普通二叉樹特殊,但又沒有滿二叉樹那么特殊,計算它的節(jié)點總數(shù),可以說是普通二叉樹和完全二叉樹的結(jié)合版,先看代碼:
public int countNodes(TreeNode root) {TreeNode l = root, r = root;// 記錄左、右子樹的高度int hl = 0, hr = 0;while (l != null) {l = l.left;hl++;}while (r != null) {r = r.right;hr++;}// 如果左右子樹的高度相同,則是一棵滿二叉樹if (hl == hr) {return (int)Math.pow(2, hl) - 1;}// 如果左右高度不同,則按照普通二叉樹的邏輯計算return 1 + countNodes(root.left) + countNodes(root.right); }結(jié)合剛才針對滿二叉樹和普通二叉樹的算法,上面這段代碼應(yīng)該不難理解,就是一個結(jié)合版,但是其中降低時間復(fù)雜度的技巧是非常微妙的。
開頭說了,這個算法的時間復(fù)雜度是 O(logN*logN),這是怎么算出來的呢?
直覺感覺好像最壞情況下是 O(N*logN) 吧,因為之前的 while 需要 logN 的時間,最后要 O(N) 的時間向左右子樹遞歸:
return 1 + countNodes(root.left) + countNodes(root.right);關(guān)鍵點在于,這兩個遞歸只有一個會真的遞歸下去,另一個一定會觸發(fā)hl == hr而立即返回,不會遞歸下去。
為什么呢?原因如下:
一棵完全二叉樹的兩棵子樹,至少有一棵是滿二叉樹:
看圖就明顯了吧,由于完全二叉樹的性質(zhì),其子樹一定有一棵是滿的,所以一定會觸發(fā)hl == hr,只消耗 O(logN) 的復(fù)雜度而不會繼續(xù)遞歸。
綜上,算法的遞歸深度就是樹的高度 O(logN),每次遞歸所花費的時間就是 while 循環(huán),需要 O(logN),所以總體的時間復(fù)雜度是 O(logN*logN)。
所以說,「完全二叉樹」這個概念還是有它存在的原因的,不僅適用于數(shù)組實現(xiàn)二叉堆,而且連計算節(jié)點總數(shù)這種看起來簡單的操作都有高效的算法實現(xiàn)。
參考:
完全二叉樹的節(jié)點數(shù),你真的會算嗎?
總結(jié)
以上是生活随笔為你收集整理的子节点随父节点高度改变_完全二叉树的子节点数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql 格林时间转换_格林时间转换成
- 下一篇: lfw2019_来自 LFW SS20