二叉树11:完全二叉树的节点个数

Leetcode 222.完全二叉树的节点个数

要求是 给出一个完全二叉树,求出该树的节点个数。

完全二叉树的节点数其实是可以在找到最后一层最右侧的元素之后直接使用公式计算的。这里我们需要先明确什么是完全二叉树,以及普通二叉树和完全二叉树的区别。

我们先不考虑完全二叉树,而是按照普通二叉树的思路来全部遍历并统计。

这道题目的递归法和求二叉树的深度写法类似, 而迭代法,用层序遍历稍稍修改一下,记录遍历的节点数就可以了。

递归遍历的顺序依然是后序(左右中)。

1.普通递归求解

还是三部曲:

1. 确定递归函数的参数和返回值:参数就是传入树的根节点,返回就返回以该节点为根节点二叉树的节点数量,所以返回值为int类型。 代码如下:

int getNodesNum(TreeNode cur) {}

2. 确定终止条件:如果为空节点的话,就返回0,表示节点数为0。 代码如下:

if (cur == null) return 0;

3. 确定单层递归的逻辑:先求它的左子树的节点数􏰁,再求的右子树的节点数􏰁,最后取总和再加一 (加1是因 为算上当前中间节点)就是目前节点为根节点的节点数量。

代码如下:

 
int leftNum = getNodesNum(cur.left); 
int rightNum = getNodesNum(cur.right); 
int treeNum = leftNum + rightNum + 1; 
return treeNum;

所以整体代码就有了,然后再精简一下就这样了:

public int countNodes(TreeNode root) {
    if (root == null){
        return 0;
    }
    return countNodes(root.left) + countNodes(root.right) + 1;
}
 

三行代码就解决问题了。

2.完全二叉树

上面的代码虽然精简,但是递归计算的代价是比较高的。如果面试官让你做这个题,即使你将上面的写出来, 他还是会让你能否利用完全二叉树的特征来提高计算效率。如果考虑完全二叉树的特性,这个题该怎么处理呢?其实有多种方式,我们就来看一下。

首先需要明确完全二叉树的定义:它是一棵空树或者它的叶子节点只出在最后两层,若最后一层不满则叶子节点只在最左侧。

再来回顾一下满二叉的节点个数怎么计算,如果满二叉树的层数为h,则总节点数为:2^h - 1.
那么我们来对 root 节点的左右子树进行高度统计,分别记为 left 和 right,有以下两种结果:

  1. left == right。这说明,左子树一定是满二叉树,因为节点已经填充到右子树了,左子树必定已经填满了。所以左子树的节点总数我们可以直接得到,是 2^left - 1,加上当前这个 root 节点,则正好是 2^left。再对右子树进行递归统计。
  2. left != right。说明此时最后一层不满,但倒数第二层已经满了,可以直接得到右子树的节点个数。同理,右子树节点 +root 节点,总数为 2^right。再对左子树进行递归查找。

完全二叉树只有两种情况,

情况一:就是满二叉树,

情况二:最后一层叶子节点没有满。

对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。

对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以 按照情况1来计算。如下图:

再看一个图:

 可以看出如果整个树不是满二叉树,就递归其左右孩子,直到遇到满二叉树为止,用公式计算这个子树(满二叉 树)的节点数量。

另外一点,就是如何计算 2^left,最快的方法是移位计算,因为运算符的优先级问题,记得加括号哦。所以代码就是:


class Solution {
    public int countNodes(TreeNode root) {
        if(root == null){
           return 0;
        } 
        int left = countLevel(root.left);
        int right = countLevel(root.right);
        if(left == right){
            return countNodes(root.right) + (1<<left);
        }else{
            return countNodes(root.left) + (1<<right);
        }
    }
    private int countLevel(TreeNode root){
        int level = 0;
        while(root != null){
            level++;
            root = root.left;
        }
        return level;
    }
}

这个题还可以使用层次的方式来统计,因为末尾节点上一层的一定是满二叉树,不过前面两种方式比较正统,比较好理解,我们就到此为止吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纵横千里,捭阖四方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值