力扣解题思路:完全二叉树 纠错记录

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


思路:题目要求统计完全二叉树的节点个数,如果抛开树的类型,我们完全可以用普通的递归的方式,比如DFS,BFS都可以:

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

但是这样完全没有利用完全二叉树的特性,首先,完全二叉树的特点是树的节点是一层一层的从左往右放的,也就是说该树的层数是完全取决于最左边的叶子节点的深度的,并且只要右边的叶子节点存在,那么其左边所有叶子节点(同一层的)就一定存在。

那么我们只需要知道该树的层数以及最后一层的叶子节点的个数,就可以算出整个树的节点数了。

如果满二叉树的层数为h,则总节点数为:2^h - 1.

那么我们来对 root 节点的左右子树进行高度统计,分别记为 left 和 right,有以下两种结果:

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

2.left != right。说明此时最后一层不满,但倒数第二层已经满了,可以直接得到右子树的节点个数。同理,右子树节点 +root 节点,总数为 2^right。再对左子树进行递归查找。

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){
    if(root == null) return 0;
    return Math.max(countLevel(root.left),countLevel(root.right)) + 1;
}

但是这样仍然没有利用完全二叉树的特性(该树的层数是完全取决于最左边的叶子节点的深度),所以代码可以改为:

private int countLevel(TreeNode root){
    int level = 0;
    while(root != null){
        level++;
        root = root.left;
    }
    return level;
}

完整代码如下:

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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值