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