漫画:二叉树系列 第七讲(完全二叉树的节点个数)

在上一篇中,我们学习了解了平衡二叉树,并且利用DFS进行了验证。在本节中,我们将继续学习完全二叉树的相关内容。首先了解一下什么是完全二叉树。

01

完全二叉树

完全二叉树由满二叉树引出,先来了解一下什么是满二叉树:

如果二叉树中除了叶子结点,每个结点的度都为 2,则此二叉树称为满二叉树。(二叉树的度代表某个结点的孩子或者说直接后继的个数。对于二叉树而言,1度是只有一个孩子或者说单子树,2度是有两个孩子或者说左右子树都有。)

比如下面这颗:

那什么又是完全二叉树呢:

如果二叉树中除去最后一层节点为满二叉树,且最后一层的结点依次从左到右分布,则此二叉树被称为完全二叉树

比如下面这颗:

而这颗就不是:

熟悉了概念,我们来看题目:

02

第222题:完全二叉树的节点个数

第222题:给出一个完全二叉树,求出该树的节点个数。

说明:

完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

示例:

输入: 

    1

   / \

  2   3

 / \  /

4  5 6

输出: 6

03

递归求解

首先分析题目,我们很容易可以想到通过递归,来求解节点个数。

1func countNodes(root *TreeNode) int {
2    if root != nil {
3        return 0
4
5    }
6    return 1 + countNodes(root.Right) + countNodes(root.Left)
7}

但是很明显,出题者肯定不是要这种答案。因为这种答案和完全二叉树一毛钱关系都没有。所以我们继续思考。

04

经典解法

由于题中已经告诉我们这是一颗完全二叉树,我们又已知了完全二叉树除了最后一层,其他层都是满的,并且最后一层的节点全部靠向了左边。那我们可以想到,可以将该完全二叉树可以分割成若干满二叉树和完全二叉树满二叉树直接根据层高h计算出节点为2^h-1,然后继续计算子树中完全二叉树节点。那如何分割成若干满二叉树和完全二叉树呢?对任意一个子树,遍历其左子树层高left,右子树层高right,相等左子树则是满二叉树,否则右子树是满二叉树。这里可能不容易理解,我们看图。

假如我们有树如下:

我们看到根节点的左右子树高度都为3,那么说明左子树是一颗满二叉树。因为节点已经填充到右子树了,左子树必定已经填满了。所以左子树的节点总数我们可以直接得到,是2^left - 1,加上当前这个root节点,则正好是2^3,即 8。然后只需要再对右子树进行递归统计即可。

那假如我们的树是这样:

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

根据分析,得出代码:

 1//java
 2class Solution {
 3    public int countNodes(TreeNode root) {
 4        if (root == null) {
 5            return 0;
 6        }
 7        int left = countLevel(root.left);
 8        int right = countLevel(root.right);
 9        if (left == right) {
10            return countNodes(root.right) + (1 << left);
11        } else {
12            return countNodes(root.left) + (1 << right);
13        }
14    }
15
16    private int countLevel(TreeNode root) {
17        int level = 0;
18        while (root != null) {
19            level++;
20            root = root.left;
21        }
22        return level;
23    }
24}

学会请留言打卡

让我看到你的努力~

注:本系列所有教程中都不会用到复杂的语言特性,大家不需要担心没有学过语法知识。算法思想最重要,使用各语言纯属本人爱好。同时,本系列所有代码均在leetcode上进行过测试运行,保证其严谨性!

温馨提示

浩仔讲算法~

每天一起学习图解漫画算法。

一起刷题,一起成长!

~长按下方二维码进行关注吧~

转载是对我最大的支持~

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值