# LeetCode 222 、完全二叉树的节点个数
# 一、题目描述
给出一个完全二叉树,求出该树的节点个数。
示例 1:
输入:root = [1,2,3,4,5,6]
输出:6
示例 2:
输入:root = []
输出:0
示例 3:
输入:root = [1]
输出:1
提示:
- 树中节点的数目范围是[0, 5 * 10^4]
- 0 <= Node.val <= 5 * 10^4
- 题目数据保证输入的树是 完全二叉树
# 二、题目解析
# 三、参考代码
# 1、Java 代码
// 登录 AlgoMooc 官网获取更多算法图解
// https://www.algomooc.com
// 作者:程序员吴师兄
// 代码有看不懂的地方一定要私聊咨询吴师兄呀
// 全二叉树的节点个数( LeetCode 222 ):https://leetcode-cn.com/problems/count-complete-tree-nodes
class Solution {
public int countNodes(TreeNode root) {
// 边界判断
// 递归终止条件,如果当前节点为 null,肯定节点个数为 0
if(root == null) {
return 0;
}
// 先获取当前节点的左子树的深度
int leftDepth = getDepth(root.left);
// 再获取当前节点的右子树的深度
int rightDepth = getDepth(root.right);
// 如果 左子树的深度 等于 右子树的深度
// 由于在完全二叉树中,对于某一层的节点来说,只有填充满了这一层的左子树的节点才会填充右子树
// 因此,这意味着左子树是满二叉树
if (leftDepth == rightDepth) {
// 对于一棵满二叉树来说
// 1
// / \
// 2 3
// 它的节点数是 2^depth - 1
// 位移操作,记得加括号,优先级比较低,不加容易出错
int leftNodes = (1 << leftDepth) - 1;
// 再去递归的获取它的右子树的节点数
int rightNodes = countNodes(root.right);
// 最后返回结果
// 注意,当前节点也是需要再统计一下的
return leftNodes + rightNodes + 1;
// 如果 左子树的深度 不等于 右子树的深度
// 由于在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值
// 因此,这意味着右子树是满二叉树
// 这样,才会出现左子树的深度比右子树的深度更深
} else {
// 对于一棵满二叉树来说
// 1
// / \
// 2 3
// 它的节点数是 2^depth - 1
// 位移操作,记得加括号,优先级比较低,不加容易出错
int rightNodes = (1 << rightDepth) - 1;
// 再去递归的获取它的右子树的节点数
int leftNodes = countNodes(root.left);
// 最后返回结果
// 注意,当前节点也是需要再统计一下的
return leftNodes + rightNodes + 1;
}
}
// 统计树的深度
private int getDepth(TreeNode curNode) {
// 默认当前节点 curNode 的深度为 0
int depth = 0;
// 只要 curNode 节点有值,就不断的判断
while (curNode != null) {
// 由于当前节点 curNode 是在一棵完全二叉树中
// 最下面一层的节点都集中在该层最左边的若干位置
// 即只有它的下一层左子树满了,才会填充右子树
// 因此,如果只需要判断 curNode 的左子树是否有值就行
curNode = curNode.left;
// 当前节点 curNode 有值,说明深度加深了一个
depth++;
}
// 返回以 curNode 作为根节点的树的深度
return depth;
}
}