A *full binary tree* is a binary tree where each node has exactly 0 or 2 children.

Return a list of all possible full binary trees with Nnodes.  Each element of the answer is the root node of one possible tree.

Each node of each tree in the answer must have node.val = 0.

You may return the final list of trees in any order.

Example 1:

Input: 7
Output: [[0,0,0,null,null,0,0,null,null,0,0],[0,0,0,null,null,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,null,null,null,null,0,0],[0,0,0,0,0,null,null,0,0]]
Explanation:

Note:

  • 1 <= N <= 20

这道题给了一个数字N,让我们生成所有包含N个结点的满二叉树。所谓的满二叉树,就是每个结点一定会有0个或2两个子结点,换句话说,子结点必须成对出现,注意跟完全二叉树区分。现在我们有N个结点可以使用,若我们仔细观察,可以发现,所有的满二叉树的结点总数都是奇数,所以只要当N为偶数的时候,一定返回的是空数组,这个可以当作一个剪枝放在开头。下面我们就来考虑当N是奇数时,如何生成不同的满二叉树。先从最简单的开始,当 N=1 时,就只有一个根结点,当 N=3 时,也只有一种情况,根结点和左右子结点,当 N=5 时,就有如下两种情况:

    0
/ \
0 0
/ \
0 0 0
/ \
0 0
/ \
0 0

我们可以看出来就是在 N=3 的情况下再多加两个结点,这两个结点可以都在左子结点下,或者都在右子结点下。但是当 N=7 的时候就比较 tricky 了,也可以看作是在 N=5 的情况下生成的,我们可以把多余出来的两个结点分别加到上面两棵树的任意一个叶结点下方,但可能你会有疑问,上面的两棵树各自都有三个叶结点,每个都加的话,不就应该有6种情况了么,其实只有5种,因为其中有两种情况是重合的,即在第一棵树的最右叶结点下添加,跟在第二棵树的最左叶结点下添加后得到的完全二叉树是一样的,所以总共只有5种组合。

讲到这里,身为读者的你可能还是比较迷茫,到底该如何用代码来生成,我们再换一种思维方式,若总共有N个结点可以分配,那么除去根结点,左右子树一共可以分配 N-1 个结点,由于N一定是奇数,那么 N-1 一定就是偶数,所以左右子树需要共同来分配这 N-1 个结点。又因为满二叉树的子树也必须是满二叉树,所以每个子树的结点总数也应该是奇数,由于 N-1 是偶数,所以这 N-1 个结点不可能全部给其中的一个子树,即左右子树至少有一个结点,那么实际上就是把 N-1 这个偶数拆分成任意两个奇数之和,比如p和q,满足 p+q = N-1,且p,q均为奇数,然后对其分别对p和q调用递归函数,得到两个数组,数组里面的就是所有可能情况的左右子树的根结点。之后要做的就是从这两个数组中任意取两个结点,加到一个新建的 cur 结点的左右子结点上,然后将 cur 结点存入结果 res 中。这种处理方法跟之前的那两道题 Unique Binary Search Trees IIDifferent Ways to Add Parentheses 一模一样,若大家眼睛够尖的话,可以看出来这其实也是 卡塔兰数 Catalan Numbe,参见代码如下:

解法一:

class Solution {
public:
vector<TreeNode*> allPossibleFBT(int N) {
if (N % 2 == 0) return {};
if (N == 1) return {new TreeNode(0)};
vector<TreeNode*> res;
for (int i = 1; i < N; i += 2) {
vector<TreeNode*> left = allPossibleFBT(i), right = allPossibleFBT(N - i - 1);
for (auto a : left) {
for (auto b : right) {
TreeNode *cur = new TreeNode(0);
cur->left = a;
cur->right = b;
res.push_back(cur);
}
}
}
return res;
}
};

我们可以通过使用一个 HashMap 来避免重复计算,从而提升运算速度,建立每个值跟其对应的满二叉树的根结点数组之间的映射,那么在递归函数中,判定完了偶数跟1的情况后,就看当前N值是否已经计算过了,是的话,直接从 HashMap 中取数组,否则就进行和上面一样的运算,最后在返回前要将结果存入 HashMap 中,参见代码如下:


解法二:

class Solution {
public:
unordered_map<int, vector<TreeNode*>> m;
vector<TreeNode*> allPossibleFBT(int N) {
if (N % 2 == 0) return {};
if (N == 1) return {new TreeNode(0)};
if (m.count(N)) return m[N];
vector<TreeNode*> res;
for (int i = 1; i < N; i += 2) {
vector<TreeNode*> left = allPossibleFBT(i), right = allPossibleFBT(N - i - 1);
for (auto a : left) {
for (auto b : right) {
TreeNode *cur = new TreeNode(0);
cur->left = a;
cur->right = b;
res.push_back(cur);
}
}
}
return m[N] = res;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/894

类似题目:

Unique Binary Search Trees II

Different Ways to Add Parentheses

参考资料:

https://leetcode.com/problems/all-possible-full-binary-trees/

[LeetCode All in One 题目讲解汇总(持续更新中...)](https://www.cnblogs.com/grandyang/p/4606334.html)

[LeetCode] 894. All Possible Full Binary Trees 所有可能的满二叉树的更多相关文章

  1. Leetcode 894. All Possible Full Binary Trees

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

  2. 【LeetCode】894. All Possible Full Binary Trees 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  3. 【LeetCode】951. Flip Equivalent Binary Trees 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 日期 题目地址:https://leetcod ...

  4. 【LeetCode】617. Merge Two Binary Trees 解题报告

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 日期 题目地址:https://leetcod ...

  5. leetcode第一天-merge two binary trees

    有段时间没有写代码了,脑子都生锈了,今后争取笔耕不辍(立flag,以后打脸) 随机一道Leecode题, Merge Two Binary Trees,题目基本描述如下: Given two bina ...

  6. 113th LeetCode Weekly Contest Flip Equivalent Binary Trees

    For a binary tree T, we can define a flip operation as follows: choose any node, and swap the left a ...

  7. 【leetcode】617. Merge Two Binary Trees

    原题 Given two binary trees and imagine that when you put one of them to cover the other, some nodes o ...

  8. LC 894. All Possible Full Binary Trees

    A full binary tree is a binary tree where each node has exactly 0 or 2 children. Return a list of al ...

  9. 【leetcode】951. Flip Equivalent Binary Trees

    题目如下: For a binary tree T, we can define a flip operation as follows: choose any node, and swap the ...

随机推荐

  1. Exercises for IN1900

    Exercises for IN1900October 14, 2019PrefaceThis document contains a number of programming exercises ...

  2. Allure+pytest 生成测试报告

    简介: python 主流自动化测试报告插件有三个:HTMLTestRunner.BeautifulReport 和 Allure.HTMLTestRunner是一个比较古老的报告模板,界面也不是很好 ...

  3. 知识图谱与Bert结合

    论文题目: ERNIE: Enhanced Language Representation with Informative Entities(THU/ACL2019) 本文的工作也是属于对BERT锦 ...

  4. Python - 字符串 - 第七天

    Python 字符串 字符串是 Python 中最常用的数据类型.我们可以使用引号( ' 或 " )来创建字符串. 创建字符串很简单,只要为变量分配一个值即可.例如: var1 = 'Hel ...

  5. Ansible varialbes

    1.什么是变量? ​ 以一个固定的字符串,表示一个不固定的值 version: 1.12 2.定义变量? 1.在playbook中定义变量? vars 关键字 [root@manager projec ...

  6. ASP.NET Core系列:日志

    1. NLog 添加安装包: Install-Package NLog.Web.AspNetCore <?xml version="1.0" encoding="u ...

  7. java SSM 框架 微信自定义菜单 快递接口 SpringMVC mybatis redis shiro ehcache websocket

    A 调用摄像头拍照,自定义裁剪编辑头像,头像图片色度调节B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,快速开发利器)+快速表单构建器 freemaker模版技术 ,0个代码不用写,生成 ...

  8. php对象复制、clone、浅复制与深复制实例详解

    php对象复制.clone.浅复制与深复制实例详解 一.用clone(克隆)来复制对象$obj1 = new Object();$obj2 = clone $obj1;clone方法会触发对象里定义的 ...

  9. 技能篇丨FineCMS 5.0.10 多个漏洞详细分析

    今天是一篇关于技能提升的文章,文章中的CMS是FineCMS,版本是5.0.10版本的几个漏洞分析,主要内容是介绍漏洞修补前和修补后的分析过程,帮助大家快速掌握该技能. 注:篇幅较长,阅读用时约7分钟 ...

  10. OC编码规范

    http://www.jianshu.com/p/8b76814b3663#class-constructor-methods