📌  相关文章
📜  计算完整二叉树中的节点数(1)

📅  最后修改于: 2023-12-03 14:57:29.489000             🧑  作者: Mango

计算完整二叉树节点数算法介绍

完整二叉树(Full Binary Tree)指每个节点都存在左右子树,且叶节点都在同一层的二叉树。计算完整二叉树中的节点数是一个经典问题,解决这个问题可以使用多种方法,本文将介绍两种常用的算法思路。

方法一:递归法

对于完整二叉树,可以分别计算左子树和右子树的节点个数,最后加上根节点即可得到完整二叉树的节点数。

递归方程如下:

countNodes(root) = countNodes(root.left) + countNodes(root.right) + 1

其中 root 为根节点。

递归出口为当 root 为空时,返回 0。

由于每一次递归都会缩小问题的规模,因此时间复杂度为 $O(logn*logn)$,空间复杂度为 $O(logn)$。

代码片段如下:

def countNodes(root: TreeNode) -> int:
    if not root:
        return 0
    return countNodes(root.left) + countNodes(root.right) + 1
方法二:二分查找法

对于已知节点数的完整二叉树,可以先求出它的高度 h,再利用二分查找来确定最后一层节点的数量。

最后一层的节点数范围是 0~$2^h-1$,可以遍历这个范围内的所有数字并检查是否存在对应的节点,时间复杂度为 $O(2^h)$。

利用二分查找可以优化这个过程。从 0~$2^h-1$ 的范围中取出中间的值 mid,检查这个值对应的节点是否存在。如果存在,则右边的范围里也一定存在节点;否则,左边的范围里一定存在节点。这样每次可以缩小范围一半,时间复杂度为 $O(h*log(2^h))$ = $O(h^2)$。由于节点数是 $2^h-1$,因此空间复杂度为 $O(logn)$。

代码片段如下:

def countNodes(root: TreeNode) -> int:
    if not root:
        return 0
    level = 0
    node = root
    while node.left:
        level += 1
        node = node.left
    l, r = 1 << level, (1 << (level + 1)) - 1
    while l < r:
        mid = (l + r + 1) // 2
        if exist(root, level, mid):
            l = mid
        else:
            r = mid - 1
    return l

def exist(root: TreeNode, level: int, k: int) -> bool:
    bits = 1 << (level - 1)
    node = root
    while node and bits > 0:
        if not (bits & k):
            node = node.left
        else:
            node = node.right
        bits >>= 1
    return node is not None
总结

本文介绍了两种计算完整二叉树节点数的算法:递归法和二分查找法。递归法简单易懂,但时间复杂度较高;二分查找法时间复杂度较低,但要求节点个数已知。可根据实际场景选取合适的算法。