平衡二叉树
题目详情:
平衡二叉树的定义是递归定义的:
(1) 单个节点是平衡二叉树
(2)平衡二叉树的左右子树分别都是平衡二叉树
(3)平衡二叉树的左右子树高度差不超过1。
求n个节点有m个叶子节点的平衡二叉树个数 (0<m <= n<=20)。
例如:
n = 1,m = 1,输出:1;
n = 2,m = 1,输出:2;
n = 2,m = 2,输出:0。
-----------------------------分割线-------------------------------
首先要明白:
1.层为level的平衡二叉树其左右子树的情况:
(1)左右子树都是层为level-1的平衡二叉树;
(2)左子树是层为level-1的平衡二叉树,右子树是层为level-2的平衡二叉树;
(3)左子树是层为level-2的平衡二叉树,右子树是层为level-1的平衡二叉树;
2.设层为level的平衡二叉树的最多结点数nodeMax,最少结点数nodeMin,最多叶子结点数leafMax和最少叶子结点数leafMin,且根据二叉树的递归定义,这四个量都是随level递增的,那么得出如下公式(下标代表层数):
nodeMin[level]=nodeMin[level-1]+nodeMin[level-2]+1;
nodeMax[level]=2* nodeMax[level-1]+1;
leafMin[level]=leafMin[level-1]+leafMin[level-2];
leafMax[level]=2*leafMin[level-1];
且初始条件是:nodeMin[0]=nodeMax[0]=leafMin[0]=leafMax[0]=0;
nodeMin[1]=nodeMax[1]=leafMin[1]=leafMax[1]=1;
计算的结果如下:
需要说明的是:层为level的二叉树节点数为n,叶子结点数为m,
那么nodeMin[level]=<n<=nodeMax[level] , leafMin[level]=<m<=leafMax[level]是此二叉树是层为level的平衡二叉树的必要非充分条件。
只有当n==m==level==1时才是充要条件,这也是3中其作为递归出口的原因。
3.设函数treeNum(n,m,level)返回的是结点数为n,叶子结点数为m,层数为level的平衡二叉树的数目,treeNum(n,m,level)如下:
int treeNum(int n,int m,int level){
if(n==m==level==1 or 0)return 1;//0代表了空树
if(level<=1)return 0;
int res=0;
for(1中的三种情况)
for(左子树的结点数leftNode<=n-1){
for(左子树的叶子结点数leftLevel<=m){
如果左右子树的结点和叶结点符合条件
res+=treeNum(leftNode,leftLeaf,leftLevel)*treeNum(rightNode,rightLeaf,rightLevel)
}
return res;
}
在递归的过程中,保证左右子树的结点数和叶子几点数满足上述四个统计量,就保证了往下递的过程某层上存在某些种形式的平衡二叉树,而找到这些平衡二叉树是在向上归的过程中实现的。
题目中只给定了n和m,那么我们首先需要通过2中的四个数组来看n和m能构成层为多少的平衡二叉树,并分别统计数量进行相加,如下:
int res=0;
for(level=1;level<size;++level)
if(n,m满足level层)
res+=treeNum(n,m,level);
当然需要将中间结果treeNum(n,m,level)用map或者hash_map保存下来防止重复计算。
5.可能是英雄会这道题的C++提交有问题,提交提示用例错误,但是将上面代码生成的数组用C提交,却通过,估计C++提交问题下周会解决。
本文参考了http://blog.csdn.net/mamihong/article/details/18304651