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. DFS(三):八皇后问题

    [例1]八皇后问题. 在一个8×8国际象棋盘上,放置8个皇后,每个皇后占一格,要求皇后间不会出现相互“攻击”的现象,即不能有两个皇后处在同一行.同一列或同一对角线上.问共有多少种不同的放置方法? (1 ...

  2. 六、Spring之初步认识AOP

    Spring之初步认识AOP [1]AOP概览 什么是AOP?(来自百度) ​ 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行 ...

  3. 5个你可能不知道的html5语义化标签

    1.<ruby>:该标签作用为注释(中文注音或字符),比如可实现下面样式  详见:https://www.w3cschool.cn/html5/html5-ruby.html 2.< ...

  4. 2019.10 搜索引擎最新排名,Elasticsearch遥遥领先

    大数据的搜索平台已经成为了众多企业的标配,Elasticsearch.Splunk(商业上市公司).Solr(Apache开源项目)是其中最为优秀和流行的选择.在2019.10 最新搜索引擎排名中,E ...

  5. 何谓SQLSERVER参数嗅探(转载)

    大家听到“嗅探”这个词应该会觉得跟黑客肯定有关系吧,使用工具嗅探一下参数,然后截获,脱裤o(∩_∩)o .事实上,我觉得大家太敏感了,其实这篇文章跟数据库安全没有什么关系,实际上跟数据库性能调优有关相 ...

  6. LinqToSql

    string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["ConsoleA ...

  7. ef linq多表查询(三表)

    var ph = (from c in reef.CQICC_CLIENT join v in reef.CQICC_VISIT_CLIENT on c.CLIENT_T_ID equals v.CL ...

  8. python接口上传图片和文件的方法

    import requests def sendImg(img_path, img_name, img_type='image/jpeg'): """ :param im ...

  9. 开发技术--浅谈python数据类型

    开发|浅谈python数据类型 在回顾Python基础的时候,遇到最大的问题就是内容很多,而我的目的是回顾自己之前学习的内容,进行相应的总结,所以我就不玩基础了,很多在我实际生活中使用的东西,我会在文 ...

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

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