看到这样一个问题,问n个结点可以组成多少个二叉树,正好自己在学,顺便写了一个函数来解决这个问题,然后一搜发现这个竟然是卡特兰数,好神奇~~~
思路分析
规定0个或者1个结点时,只有一种二叉树。那么对于个结点,我们不妨向前想一想,利用,甚至更前的情况来进行推理,假设个结点有种二叉树。
首先,我们先拿一个结点作为根结点,剩下了个结点,此时我们不妨将这个结点再一次分成两份,比如,0和,那么这个结点就会有种二叉树作为根结点的左子树或者右子树;同理,0个结点就会有种(即1种)二叉树作为左子树或者右子树。那么就会有这种情况:
左子树的数目 | 右子树的数目 |
---|---|
进而,我们对个结点进行多种这样的划分,每一次都会有对应的二叉树数目作为左子树或者右子树,就像这样
左子树的数目 | 右子树的数目 |
---|---|
...... | ....... |
这时我们再去对的奇偶性进行讨论。如果为奇数,那么最后会有和,顺序进行互换就有两种了;如果为偶数,那么最后就只有两个这一种分法了。当顺序互换时,总的二叉树数目就等于左子树数目右子树数目2;针对两个这种特殊情况,二叉树数目就不需要2了。
综上我们需要做的就是从0开始进行遍历,如果为奇数就遍历到,每次2;如果为偶数就遍历到,最后一个单独从循环中拿出来不用2即可。
代码实现
我是写了一个函数进行递归,供大家参考。
#include<stdio.h>
int numsofBinarytree(int n){
int res=0;
if(n==1||n==0){
return 1;
}
else{
if((n-1)%2==0){
for(int i=0;i<(n-1)/2;i++){
res+=numsofBinarytree(i)*numsofBinarytree(n-1-i)*2;
}
res+=numsofBinarytree((n-1)/2)*numsofBinarytree((n-1)/2);
}
else{
for(int i=0;i<=(n-1)/2;i++){
res+=numsofBinarytree(i)*numsofBinarytree(n-1-i)*2;
}
}
}
return res;
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
printf("%d\n",numsofBinarytree(n));
}
return 0;
}
欢迎大家在评论区提出更好的解法和思路,如果觉得有用,点个赞和收藏加关注再走吧~~~