LeetCode刷题——894. 所有可能的满二叉树

一、原题链接

  [所有可能的满二叉树](https://leetcode-cn.com/problems/all-possible-full-binary-trees/)


在这里插入图片描述

二、题解

  由题目描述可知,一个满二叉树的子树一定也是一个满二叉树。假定函数FBT(N)返回包含N个结点的所有可能满二叉树的数量,则容易推导出以下公式:
   FBT(N) = 1 + FBT(x) + FBT(N-1-x)。
   上述式子中,FBT(x)表示其左子树若含有x个结点时,能组成的所有的满二叉树的数目,FBT(N-1-x)表示其右子树含有N-1-x个结点时,能组成的所有的满二叉树的数量;式子右端+1则是表示以当前根结点组成了一棵树。N-1-x则是因为树中一共包含N个结点,减去根结点和左子树中的x个结点,则右子树中有N-1-x个结点。
   同时,考虑几种特殊情况,如下:
  1、N=0时,是一棵空树,直接返回空列表;
   2、N=1时,构成只有一个结点的树;
  3、由定义可知,N为偶数时构不成满二叉树。

三、代码实现

  具体到代码实现时,选择递归的方式。为了避免重复的计算,我们采用记忆化的方式,利用一个哈希表来记录N个结点能构成的满二叉树的情况,哈希表中key值是结点数目N,对应的value值是结点数目为N时,所有可能的满二叉树组合成的列表,列表中的每一个元素都是一个满二叉树的根结点。
  在函数FBT中,首先检查哈希表中是否存在结点为N的情况。不存在的话,则递归处理。
  代码中,res中的元素将是满二叉树的根结点,元素的个数则是N个结点能够成的满二叉树的数量。
  考虑代码 for leftNode in range(1, N, 2),这里之所以每次循环给leftNode加2,是因为左子树的数量只能是1、3、5、7、9……

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


class Solution:
    def allPossibleFBT(self, N: int) -> List[TreeNode]:
        hashtable = {0:[], 1:[TreeNode(0)]}   # 做记忆化用


        def FBT(N):
            # 首先查看在哈希表中是否已经存在可能的值
            if N in hashtable:
                return hashtable[N]
            # 最终res中记录的是N个结点能组成的满二叉树的所有情况
            res = []
            for leftNode in range(1,N,2):
                rightNode = N-1-leftNode
                # FBT(leftNode)中存在结点数为leftNode时能组成的满二叉树的所有情况
                for left in FBT(leftNode):
                        # FBT(rightNode)中存在结点数为rightNode时能组成的满二叉树的所有情况
                    for right in FBT(rightNode):
                        #  建立根结点,组合所有情况,得到结点数为N时能组成的满二叉树的情况,并添加到res
                        root = TreeNode(0)
                        root.left = left
                        root.right = right
                        res.append(root)
            hashtable[N] = res
            return res
        FBT(N)
        return hashtable[N]

四、补充

  为了方便理解,补充一下对于同一个结点数目N而言,hashtable[N],FBT(N)中到底保存的是啥?
  肯定的是,对于同一个N,二者都是列表,列表中保存的是一个个树,保存的内容是一样的。
   N=1时,只能组成一种树,hashtable[1] = FBT(1) = [TreeNode(0)],如图:

在这里插入图片描述

   N=3时,同样只能组成一个树,记为A,hashtable[3] = FBT(3) = [A],A为:

在这里插入图片描述

   N=5时,能组成两个树,记为A、B,hashtable[5] = FBT(5) = [A、B],A、B如图:

在这里插入图片描述

  因此代码中,建立双重循环遍历FBT(leftNode)和FBT(rightNode),其实就是遍历两个列表,在循环体中每次取出来左子树和右子树的一种可能情况,建立根结点,组成一个树。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值