題目
計算完全二叉樹的節點數,復雜度小于O(N)
思路
由于要求復雜度為小于O(N),那么遍歷所有節點的方式肯定是不可能的了。那么回顧完全二叉樹概念
設二叉樹的深度為h,除第 h 層外,其它各層 (1~h-1) 的結點數都達到最大個數,
第 h 層所有的結點都連續集中在最左邊。
那么我們知道一個滿二叉樹的節點數,滿足以下公式,h為二叉樹的高度:
節點數 = 2^h - 1
所以,對于完全二叉樹,其總是滿足以下兩種情形:
1、node的右子樹,到達底部,說明node的左子樹是滿二叉樹,如圖所示:
node的右子樹到達底部
2、node的右子樹,沒有到達底部,說明node的右子樹是底層高度 - 1 的滿二叉樹,如圖所示:
node的右子樹沒有到達底部
那么,根據以上兩個情況,我們可以遞歸的求每個節點的節點數
算法實現
public static int completeTreeNum(Node head) {
if (head == null) {
return 0;
}
return bs(head, 1, mostLeftLevel(head, 1));
}
/// 以node為節點的完全二叉樹,返回其節點數
/// node代表當前節點
/// level代表node在第幾層
/// h代表左樹的總高度
public static int bs(Node node, int level, int h) {
// 說明已經到最后一層了,那么就是node就是葉節點
if (level == h) {
return 1;
}
// node的右子樹高度已經到底,說明node的左樹是滿二叉樹
// 因此該樹的節點數 = 左邊滿二叉樹(2^(h - level) - 1) + node節點 + node的右節點數
if (mostLeftLevel(node.right, level + 1) == h) {
return (int)Math.pow(2, h - level) + bs(node.right, level + 1, h);
}else {
// 說明左子樹比右子樹高一層,那么node右樹就是滿二叉樹
// 因此該樹的節點數為:
// 右邊滿二叉樹(2^(h - level - 1) - 1) + node節點 + node的左節點數
return (int)Math.pow(2, h - level - 1) + bs(node.left, level + 1, h);
}
}
/// 求node節點的左子樹高度
/// node代表當前節點
/// level為node節點的高度
public static int mostLeftLevel(Node node, int level) {
while (node != null) {
level++;
node = node.left;
}
return level - 1;
}