已知前序遍历结果,求满足结果的二叉树个数?(n个节点能够构成多少种二叉树?) —— 卡特兰数

1. 背景

今天复习数据结构的时候遇到一个题目,内容如下:

【2015统考真题】先序序列为a,b,c,d的不同二叉树的个数为()
  A. 13      B.14      C.15       D.16

王道答案如下:

在这里插入图片描述

个人感觉有点难理解,为什么可以把原题目等价为"以序列a,b,c,d为入栈次序,则出栈序列的个数为?",这其中的联系在哪?在查阅了许多资料后,我决定从另一个方向来重新分析这个问题。

2. 题目分析

“已知先序序列的结果,求满足的二叉树的个数?”,首先让我们来想一想,题目给的先序序列的结果在这里起到了什么限制作用吗?答案是:没有。原题目等价于“已知一个二叉树有n个节点,求不同的二叉树的个数”,题目所给的先序序列仅仅告诉我们,二叉树的节点个数为4。

这听起来似乎有点违背直觉,难道先序遍历的结果没有任何作用吗?不要着急,请听我慢慢解释。

以3个节点的二叉树为例

3个节点构成的不同的二叉树共有5种,分别为:
在这里插入图片描述
先序序列为a,b,c的二叉树有5种,分别为:
在这里插入图片描述
先序遍历a,c,b的二叉树也是5种,分别为:
在这里插入图片描述
通过观察可以发现,三者的结果个数是一样的!也就是说,对于给定的遍历结果,只是把字母对应的填进了n个节点构成的所有的二叉树中而已,遍历的结果是什么并不会影响二叉树的数量。

由此我们还可以得出推论:

  1. 给定二叉树先序遍历结果,求满足结果的不同的树的个数
  2. 给定二叉树中序遍历结果,求满足结果的不同的树的个数
  3. 给定二叉树后序遍历结果,求满足结果的不同的树的个数
  4. 给定二叉树层序遍历结果,求满足结果的不同的树的个数

以上问题全部与 “n个节点能够构成的不同的二叉树的个数?” 等价

但是我们要如何求出n个节点能够构成的二叉树的数量呢?这似乎也是一个难以解决的问题。想要解决这个问题就需要介绍一下大名鼎鼎的"卡特兰数"了。

3. 问题求解

3.1 卡特兰数

卡特兰数是组合数学中一个常出现于各种计数问题中的数列。以中国蒙古族数学家明安图和比利时数学家欧仁·查理·卡特兰的名字命名,其前几项为(从第0项开始):1, 1, 2, 5, 14, 42…

关于卡特兰数的具体内容不做过多介绍,感兴趣的读者可以自行查阅,我们主要来看卡特兰数的形式:

h ( n ) h(n) h(n)为卡特兰数的第 n n n项,其中 h ( 0 ) = 1 , h ( 1 ) = 1 h(0)=1,h(1)=1 h(0)=1,h(1)=1,则卡特兰数满足递推式 ( n ≥ 2 ) (n \geq 2) (n2):
h ( n ) = ∑ i = 0 n − 1 h ( i ) ∗ h ( n − 1 − i ) = h ( 0 ) ∗ h ( n − 1 ) + h ( 1 ) ∗ h ( n − 2 ) + ⋯ + h ( n − 1 ) ∗ h ( 0 ) h(n) = \sum_{i=0}^{n-1}h(i)*h(n-1-i)=h(0)*h(n-1)+h(1)*h(n-2)+\cdots+h(n-1)*h(0) h(n)=i=0n1h(i)h(n1i)=h(0)h(n1)+h(1)h(n2)++h(n1)h(0)
递推关系的解为:
h ( n ) = 1 n + 1 C 2 n n h(n) = \frac{1}{n+1}C_{2n}^n h(n)=n+11C2nn
接下来,我们借助卡特兰数的公式来推出n个节点能够构成的不同的二叉树的个数。

3.2 推导过程

3.2.1 三个节点的情况

h ( n ) h(n) h(n) n n n个节点能够构成的不同的二叉树的个数,这里认为空树也算作一种,即 h ( 0 ) = 1 h(0)=1 h(0)=1,同时不难得出 h ( 1 ) = 1 , h ( 2 ) = 2 h(1)=1,h(2)=2 h(1)=1,h(2)=2

接下来我们以 n = 3 n=3 n=3为例进行推导:
在这里插入图片描述
如图,3个节点中使用1个作为根结点,对于剩余的2个节点可以进行如下的分配方法:

  1. 2个节点构成根节点的左子树,0个节点构成根节点的右子树,共有 h ( 2 ) ∗ h ( 0 ) h(2)*h(0) h(2)h(0)种结果
  2. 1个节点构成根节点的左子树,1个节点构成根节点的右子树,共有 h ( 1 ) ∗ h ( 1 ) h(1)*h(1) h(1)h(1)种结果
  3. 0个节点构成根节点的左子树,2个节点构成根节点的右子树,共有 h ( 0 ) ∗ h ( 2 ) h(0)*h(2) h(0)h(2)种结果

综上所述:3个节点构成的不同的二叉树的个数为: h ( 3 ) = h ( 2 ) ∗ h ( 0 ) + h ( 1 ) ∗ h ( 1 ) + h ( 0 ) ∗ h ( 2 ) = 5 h(3)=h(2)*h(0)+h(1)*h(1)+h(0)*h(2)=5 h(3)=h(2)h(0)+h(1)h(1)+h(0)h(2)=5

3.2.2 n个节点的情况

将上述结论推广到 n n n个节点:
在这里插入图片描述
同理,1个节点作为根节点,剩余 n − 1 n-1 n1个节点可以按上述分配方法进行分配,可以得到:
h ( n ) = h ( n − 1 ) ∗ h ( 0 ) + h ( n − 2 ) ∗ h ( 1 ) + ⋯ + h ( 1 ) ∗ h ( n − 2 ) + h ( 0 ) ∗ h ( n − 1 ) h(n)=h(n-1)*h(0)+h(n-2)*h(1)+\cdots+h(1)*h(n-2)+h(0)*h(n-1) h(n)=h(n1)h(0)+h(n2)h(1)++h(1)h(n2)+h(0)h(n1)
正好满足卡特兰数的递推式,即:
h ( n ) = 1 n + 1 C 2 n n h(n)=\frac{1}{n+1}C_{2n}^n h(n)=n+11C2nn

4.总结

对于一个给定的遍历结果(不论是先序遍历、中序遍历、后序遍历还是层序遍历),其对应的不同的二叉树的个数等于n个节点构成的不同的二叉树的个数,即为卡特兰数

卡特兰数可以由下述公式进行计算:
h ( n ) = 1 n + 1 C 2 n n h(n)=\frac{1}{n+1}C_{2n}^n h(n)=n+11C2nn

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值