一、需求
- 给你一棵 完全二叉树 的根节点
root
,求出该树的节点个数; -
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置;
-
若最底层为第 h 层,则该层包含 1~
个节点;
输入:root = [1,2,3,4,5,6] 输出:6
提示:
- 树中节点的数目范围是
[0, 5 * 104]
0 <= Node.val <= 5 * 104
- 题目数据保证输入的树是 完全二叉树
进阶:遍历树来统计节点是一种时间复杂度为
O(n)
的简单解决方案。你可以设计一个更快的算法吗?
二、前序遍历
2.1 思路分析
- 该题目只是统计完全二叉树中的节点个数,我们直接按二叉树来做,前序/中序/后序均可;
2.2 代码实现
class Solution {
public int countNodes(TreeNode root) {
if(root == null) {
return 0;
}
return 1 + countNodes(root.left) + countNodes(root.right);
}
}
2.3 复杂度分析
- 时间复杂度为O(N);
- 空间复杂度为O(N);
三、递归法
3.1 思路分析
- 我们可以将原问题:完全二叉树的节点个数转换为 1 + 左子树节点个数 + 右子树节点个数;
- 这次我们不用前序遍历,通过利用完全二叉树的性质来做,它有这样的情况:①它是一棵空树;②叶子节点只出现在最后两层,若最后一层不满,则叶子节点只出现在最左侧;
- 根据这样的性质,我们利用树的深度来计算节点个数,而不是遍历树的每一个节点,众所周知,当满二叉树的深度为 h 时,其节点个数为
;
- 我们求解当前节点左子树的深度leftTreeHeight和右子树的深度rightTreeHeight,存在两种情况:①leftTreeHeight == rightTreeHeight,那么左子树必然是满二叉树,加上当前节点,则深度为
,此时再加上右子树的节点数;②leftTreeHeight > rightTreeHeight,此时右子树必然是满二叉树,加上当前节点,则深度为
,再加上左子树的节点数;
- 关于如何求解树的深度,可以使用递归法,也可以根据完全二叉树的性质使用迭代,因此树的最大深度一定是由当前树最后一层的左子节点决定的,故只需遍历到最后一层最左侧的那个左子节点即可;
3.2 代码实现
class Solution {
public int countNodes(TreeNode root) {
if(root == null) {
return 0;
}
int leftTreeDepth = countDepth(root.left);
int rightTreeDepth = countDepth(root.right);
if(leftTreeDepth == rightTreeDepth) {
return countNodes(root.right) + (1 << leftTreeDepth);
} else {
return countNodes(root.left) + (1 << rightTreeDepth);
}
}
//该方法计算树的高度
private int countDepth(TreeNode root) {
int depth = 0;
if(root == null) {
return 0;
}
while(root != null) {
depth++;
root = root.left;
}
return depth;
}
}
3.3 复杂度分析
- 时间复杂度为
;
- 空间复杂度为O(1);
四、学习地址
作者:xiao-ping-zi-5