Count Complete Tree Nodes

Given a complete binary tree, count the number of nodes.

Definition of a complete binary tree from Wikipedia: In a complete binary tree every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2h nodes inclusive at the last level h.

题目大意:

给定一棵完全二叉树,计算其中节点的个数。

维基百科关于完全二叉树的定义如下:

在一棵完全二叉树的每一层,除最后一层外,其余各层都是填满的,并且最后一层的节点尽可能的靠左排列。最后一层(第h层)包含的节点个数介于[1, 2^h]区间之内。

定义 :

这道题给定了一棵完全二叉树,让我们求其节点的个数。很多人分不清完全二叉树和满二叉树的区别,下面让我们来看看维基百科上对二者的定义:完全二叉树 (Complete Binary Tree)

A Complete Binary Tree (CBT) is a binary tree in which every level, except possibly the last, is completely filled, and all nodes are as far left as possible.

对于一颗二叉树,假设其深度为d(d>1)。除了第d层外,其它各层的节点数目均已达最大值,且第d层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树;

换句话说,完全二叉树从根结点到倒数第二层满足完美二叉树,最后一层可以不完全填充,其叶子结点都靠左对齐。

完美二叉树 (Perfect Binary Tree)

A Perfect Binary Tree(PBT) is a tree with all leaf nodes at the same depth. All internal nodes have degree 2.

二叉树的第i层至多拥有个节点数;深度为k的二叉树至多总共有个节点数,而总计拥有节点数匹配的,称为“满二叉树”;

完满二叉树 (Full Binary Tree):

A Full Binary Tree (FBT) is a tree in which every node other than the leaves has two children.

换句话说,所有非叶子结点的度都是2。(只要你有孩子,你就必然是有两个孩子。)

解题思路:

递归

通过上面的定义,我们可以看出二者的关系是,完美二叉树一定是完全二叉树,而完全二叉树不一定是完美二叉树。那么这道题给的完全二叉树就有可能是完美二叉树,若是完美二叉树,节点个数很好求,为2的h次方-1,h为该完美二叉树的高度。这道题可以用递归和非递归两种方法来解。我们先来看递归的方法,思路是分别找出以当前节点为根节点的左子树和右子树的高度并对比,如果相等,则说明是满二叉树,直接返回节点个数,如果不相等,则节点个数为左子树的节点个数加上右子树的节点个数再加1(根节点),其中左右子树节点个数的计算可以使用递归来计算,参见代码如下:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):

    def findSplitDepth(self, root):
        if not root:
            return 0
        else:
            root = root.right
            dep = 0
            while root:
                root = root.left
                dep += 1
            return dep

    def countNodes(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        dep = 1
        tmp = root
        while tmp.left:
            dep += 1
            tmp = tmp.left

        cur_root = root
        cur_dep = 1
        res = 0
        while cur_dep < dep:
            dd = self.findSplitDepth(cur_root)
            if dd + cur_dep == dep:
                cur_root = cur_root.right
                res += pow(2, dd-1)
                cur_dep += 1
            else:
                cur_root = cur_root.left
                cur_dep += 1

        return pow(2, dep-1) + res

Last updated

Was this helpful?