如果二叉树中除了叶子节点,每个节点的度为2.,则此二叉树称为满二叉树。(二叉树的度代表某个节点的孩子或者说直接后继的个数。对于二叉树而言,1度是只有一个孩子或者说单子树,2度是有两个孩子或者说左右子树都有。)
比如下面这颗:
那什么是完全二叉树呢:
如果二叉树出去最后一层节点为满二叉树,且最后一层的节点依次从左到右分布,则此二叉树被称为完全二叉树。
比如下面这颗:
下面这颗就不是:
递归求解:
class Solution {
public int countNodes(TreeNode root) {
if (root == null) {
return 0;
}
return 1 + countNodes(root.left) + countNodes(root.right);
}
}
经典解法:
由于题中已经告诉我们这是一颗完全二叉树,我们又已知了完全二叉树除了最后一层,其他层都是满的,并且最后一层的节点全部靠向了左边。那我们可以想到,可以将该完全二叉树可以分割成若干满二叉树和完全二叉树,满二叉树直接根据层高h计算出节点为2^h-1,然后继续计算子树中完全二叉树节点。那如何分割成若干满二叉树和完全二叉树呢?对任意一个子树,遍历其左子树层高left,右子树层高right,相等左子树则是满二叉树,否则右子树是满二叉树。这里可能不容易理解,我们看图。
假如我们有树如下:
我们看到根节点的左右子树高度都为3,那么说明左子树是一颗满二叉树。因为节点已经填充到右子树了,左子树必定已经填满了。所以左子树的节点总数我们可以直接得到,是2^left - 1,加上当前这个root节点,则正好是2^3,即 8。然后只需要再对右子树进行递归统计即可。
那假如我们的树是这样:
我们看到左子树高度为3,右子树高度为2。说明此时最后一层不满,但倒数第二层已经满了,可以直接得到右子树的节点个数。同理,右子树节点+root节点,总数为2right,即22。再对左子树进行递归查找。
class Solution {
public int countNodes(TreeNode root) {
if (root == null) {
return 0;
}
int rightLevel = countLevel(root.right);
int leftLevel = countLevel(root.left);
if (rightLevel == leftLevel) {
return countNodes(root.right) + (1 << leftLevel);
} else {
return countNodes(root.left) + (1 << rightLevel);
}
}
private int countLevel(TreeNode root) {
int level = 0;
- (1 << rightLevel);
}
}
private int countLevel(TreeNode root) {
int level = 0;
[外链图片转存中…(img-GnPQrCpH-1635263164121)]