LeetCode 222: 完全二叉樹的節點個數(java)

給出一個完全二叉樹,求出該樹的節點個數。

說明:

完全二叉樹的定義如下:在完全二叉樹中,除了最底層節點可能沒填滿外,其餘每層節點數都達到最大值,並且最下面一層的節點都集中在該層最左邊的若干位置。若最底層爲第 h 層,則該層包含 1~ 2h 個節點。

示例:

輸入: 
    1
   / \
  2   3
 / \  /
4  5 6

輸出: 6

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int countNodes(TreeNode root) {
        if(root == null) return 0;
    }
    
    int left = countLevel(root.left);
    int right = countLevel(root.right);
    
    if(left = right){
        return countNodes(root.right) + (1<<root.left);
    }else{
        return countNodes(root.left)+(1<<root.right)
    }
    
    private int countLevel(TreeNode root){
        int level = 0;
        while(root != null){
            root = root.left;
            k++;
        }
        return level;   

}

方法一:線性時間
算法:

最簡單的解決方法就是用遞歸一個一個的計算節點。


class Solution {
  public int countNodes(TreeNode root) {
    return root != null ? 1 + countNodes(root.right) + countNodes(root.left) : 0;
  }
}


複雜度分析

時間複雜度:\mathcal{O}(N)O(N)。
空間複雜度:\mathcal{O}(d) = \mathcal{O}(\log N)O(d)=O(logN),其中 dd 指的是樹的的高度,運行過程中堆棧所使用的空間。
方法二:二分搜索
方法一沒有利用完全二叉樹的特性。完全二叉樹中,除了最後一層外,其餘每層節點都是滿的,並且最後一層的節點全部靠向左邊。

這說明如果第 k 層不是最後一層,則在第 k 層中將有 2^k 個節點。由於最有一層可能沒有完全填充,則節點數在 1 到 2^d 之間,其中 d 指的是樹的高度。

我們可以直接計算除了最後一層以外的所有結點個數:


 

現在有兩個問題:

最後一層我們需要檢查多少個節點?
一次檢查的最佳的時間性能是什麼?
讓我們從第一個問題開始思考。最後一層的葉子節點全部靠向左邊,我們可以用二分搜索只檢查葉子代替檢查全部葉子。

 

讓我們思考第二個問題,最後一層的葉子節點索引在 0 到 $2^d - 1$ 之間。如何檢查第 idx 節點是否存在?讓我們來用二分搜索來構造從根節點到 idx 的移動序列。如,idx = 4。idx 位於 0,1,2,3,4,5,6,7 的後半部分,因此第一步是向右移動;然後 idx 位於 4,5,6,7 的前半部分,因此第二部是向左移動;idx 位於 4,5 的前半部分,因此下一步是向左移動。一次檢查的時間複雜度爲 {O}(d)O(d)。

我們需要{O}(d)O(d) 次檢查,一次檢查需要{O}(d)O(d),所以總的時間複雜度爲{O}(d^2)O(d`2 )。

算法:

class Solution:
    def compute_depth(self, node: TreeNode) -> int:
        """
        Return tree depth in O(d) time.
        """
        d = 0
        while node.left:
            node = node.left
            d += 1
        return d

    def exists(self, idx: int, d: int, node: TreeNode) -> bool:
        """
        Last level nodes are enumerated from 0 to 2**d - 1 (left -> right).
        Return True if last level node idx exists. 
        Binary search with O(d) complexity.
        """
        left, right = 0, 2**d - 1
        for _ in range(d):
            pivot = left + (right - left) // 2
            if idx <= pivot:
                node = node.left
                right = pivot
            else:
                node = node.right
                left = pivot + 1
        return node is not None
        
    def countNodes(self, root: TreeNode) -> int:
        # if the tree is empty
        if not root:
            return 0
        
        d = self.compute_depth(root)
        # if the tree contains 1 node
        if d == 0:
            return 1
        
        # Last level nodes are enumerated from 0 to 2**d - 1 (left -> right).
        # Perform binary search to check how many nodes exist.
        left, right = 1, 2**d - 1
        while left <= right:
            pivot = left + (right - left) // 2
            if self.exists(pivot, d, root):
                left = pivot + 1
            else:
                right = pivot - 1
        
        # The tree contains 2**d - 1 nodes on the first (d - 1) levels
        # and left nodes on the last level.
        return (2**d - 1) + left

 

 

作者:LeetCode
鏈接:https://leetcode-cn.com/problems/count-complete-tree-nodes/solution/wan-quan-er-cha-shu-de-jie-dian-ge-shu-by-leetcode/
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

 

 

 

 

 

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/count-complete-tree-nodes
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章