[路飞]_算法成长之路四十六, 完全二叉树的节点个数

164 阅读2分钟

个人算法成长之路四十六!!!定期更新一些刷题过程中个人的思路以及理解。有兴趣的朋友们可以互动交流哈~

题目:

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

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

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

 

示例 1:

image.png

输入:root = [1,2,3,4,5,6]
输出:6

示例 2:

输入:root = []
输出:0

示例 3:

输入:root = [1]
输出:1

解题思路:

image.png 对于一个完全二叉树 complete binary tree:

  • 它的所有子树都是完全二叉树

  • 有的子树是 perfect binary tree

  • perfect binary tree 的节点个数很好计算:2^h-1,h为高度

  • 如果不是 perfect binary tree,那就是规模小一点的完全二叉树,递归处理。

完全二叉树   1                      
            / \
完美二叉树 2   3    
          / \  /
         4   5 6     
--------------------  其实左右子树至少有一个是 full binary tree
    1 完全二叉树                      
   / \
  2   3 完美二叉树
 /   
4

所以对于每个节点 root,都判断一下它是否是满二叉树——左侧的高度 == 右侧的高度。

full binary tree   1                      
                 /  \
                2    3    
               / \  / \
左侧深度 3    4   5 6  7    右侧深度 3   

代码

func countNodes(root *TreeNode) int { // 返回以root为根节点的子树的节点个数
    if root == nil { // 递归的出口
        return 0
    }
    lH, rH := 0, 0  // 两侧高度
    lNode, rNode := root, root // 两个指针

    for lNode != nil {  // 计算左侧高度
        lH++
        lNode = lNode.Left
    }
    for rNode != nil {  // 计算右侧高度
        rH++
        rNode = rNode.Right
    }
    if lH == rH {        // 当前子树是满二叉树,返回出节点数
        return 1<<lH - 1 // 左移n位就是乘以2的n次方
    }
    // 当前子树不是完美二叉树,只是完全二叉树,递归处理左右子树
    return 1 + countNodes(root.Left) + countNodes(root.Right)
}