222. 完全二叉树的节点个数
给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
解:
- 利用完全二叉树的特性,即对于一个节点来说,如果它的右子树深度不等于整棵树的深度,那么右子树就是满二叉树。反之左子树就是满二叉树
- 所以,先遍历二叉树的左边界求出树的深度,然后开始递归。
- 递归参数含义为,node:当前节点。deep:当前节点深度
- 遍历当前节点右子树的左边界,求右子树能达到的深度。如果右子树深度等于整棵树的深度,那么已知当前节点深度、整棵树深度、左子树是满二叉树,就可以求出左子树的节点个数。然后去递归计算当前节点的右子树。
- 如果右子树深度不等,那么已知当前节点深度、右子树深度、右子树是满二叉树,就可以求出右子树节点个数。然后去递归计算当前节点的左子树。
- 上述两种情况,计算出子树节点个数之后,就把子树节点数 + 1(即当前节点)累加到resCount中,最终返回resCount
const countNodes = function(root) {
if (!root) return 0
let curNode = root
let treeDeep = 1
let resCount = 0
// 计算树的深度
while (curNode?.left) {
treeDeep++
curNode = curNode.left
}
const getRes = (node, deep) => {
if (!node) return
// 计算右子树深度
let curNode = node.right
let rightDeep = curNode ? deep + 1 : deep
while (curNode?.left) {
rightDeep++
curNode = curNode.left
}
// 如果右树深度等于树的深度,那么意味着左子树是满二叉树
if (rightDeep === treeDeep) {
// 计算左子树节点个数 + 根节点并累加
resCount += 2 ** (treeDeep - deep)
// 递归计算右子树的节点个数
getRes(node.right, deep + 1)
} else {
// 右子树深度小于树的深度,意味着右子树是满二叉树
// 计算右子树节点个数并累加
resCount += 2 ** (rightDeep - deep)
// 递归计算左子树节点个数+根节点
getRes(node.left, deep + 1)
}
}
getRes(root, 1)
return resCount
};