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. python-6-for循环及format三种用法

    前言 循环我们前面讲过了无限循环,那么for循环属于什么循环呢?显然就是有限循环: 另外格式化输出我们前面也讲过,但是format也能做到不一样的格式化输出.一起看看吧! 一.for 循环 1.fro ...

  2. LeetCode 151:给定一个字符串,逐个翻转字符串中的每个单词 Reverse Words in a String

    公众号:爱写bug(ID:icodebugs) 翻转字符串里的单词 Given an input string, reverse the string word by word. 示例 1: 输入: ...

  3. php,mysql结合js解决商品分类问题,从而不必联表查询

    首先mysql数据表中的商品分类用varchar类型,比如AA,BB,CC,DD等 其次编写一个js文件,用于定义常量,比如 ‘AA’ = ‘中药’;  'BB' = '西药'; 'CC' = '保健 ...

  4. vuex 源码分析(五) action 详解

    action类似于mutation,不同的是Action提交的是mutation,而不是直接变更状态,而且action里可以包含任意异步操作,每个mutation的参数1是一个对象,可以包含如下六个属 ...

  5. 阿里云 CDN 业务基于边缘容器的云原生转型实践

    导读:本文基于边缘容器的阿里云 CDN 云原生实践, 涵盖了边缘容器的背景和趋势,边缘托管集群 ACK Managed Edge K8s(文中简称“Edge@ACK”) 的能力.架构,以及基于边缘容器 ...

  6. Logstash:Data转换,分析,提取,丰富及核心操作

    Logstash:Data转换,分析,提取,丰富及核心操作 Logstash plugins Logstash是一个非常容易进行扩张的框架.它可以对各种的数据进行分析处理.这依赖于目前提供的超过200 ...

  7. [Flutter] 转一个Flutter学习思维导图

    本文的思维导图均转自QQ群,感谢原作者(是谁?) 表单 按钮 视图 Sliver 路由 (Routes) 输入控件 对话框 MDC (Material Design Component) 状态管理 R ...

  8. wpf的控件树

    转载自:控件树

  9. Scrapy 运行多个爬虫

    本文所使用的 Scrapy 版本:Scrapy==1.8.0 一个 Scrapy 项目下可能会有多个爬虫,本文陈述两种情况: 多个爬虫 所有爬虫 显然,这两种情况并不一定是等同的.假设当前项目下有 3 ...

  10. Python TK编程第一部分 Hello Again

    当你想写大一点的程序的时候,将你的代码封装到一个或者多个类里会是一个不错的办法.下面'hello world'这个例子来自Matt Conway的Tkinter Life Preserver. fro ...