算法导论12-4 N个结点的二叉树,能构成多少种形状不同的二叉树?
这个问题的答案就是著名的Catalan数,以下为详细证明过程:
此题还可以通过组合数学的方法解决,在Knuth的著作TAOCP中有非常经典的证明:
原题如此描述, n个数在入栈序列一定的情况下,其合法的出栈序列有多少种?
将入栈事件用1表示,出栈事件用0表示,则n个数的出入栈为n个1和n个0的一个排列,而且从左往右数1一定不能比0少(否则某个时刻出栈次数多于入栈次数)。
n个1和n个0的一个排列,其总数有C(2n,n),但其中还要去除那些非法的排列,以下计算非法的排列数,要证明每一个非法排列与n-1个1和n+1个0的排列等价。
(1) 一个n-1个1和n+1个0的排列可以映射到一个非法排列
由于0比1的个数多,则一定存在某个位置,此位置值为0,且前面的0和1的个数一样多,找出第一次有这种属性的位置,将其后的0和1颠倒,如此得到一个n个1和n个0的排列,其为非法的出栈序列
(2) 一个非法排列可以映射到一个n+1个1和n-1个0的排列
非法序列的含义,即存在某个位置,此位置值为0,且前面的0和1的个数一样多,找出第一次有这种属性的位置,将其后的0和1颠倒,如此得到一个n-1个1和n+1个0的排列。
所以证明了每一个非法排列与n-1个1和n+1个0的排列等价,而n-1个1和n+1个0的排列总数为C(2n,n+1),所以合法的出栈序列总数为C(2n,n)-C(2n,n+1)
以下还要证明n个数的合法出栈序列满足Catalan数的定义
进栈序列为1,2,3,…,n,假设最后一个出栈的数为k,则1,2,...,k-1必定在k入栈之前出栈了,否则k就不是最后一个出栈的数。由此合法出栈总数为1,2,...,k-1的出栈序列总数加上k+1,k+2,...,n的出栈序列总数,其中k的取值可以从0到n,则合法排列总数B(n)=sum(B(k) B(n-1-k)) (0<=k<=n-1),显然这个数目与Catalan数的定义完全一致。
其实以上的证明步骤可以等价于一棵二叉树,只要将最后出栈的数定义为树根,在边序列定义为左子树,右边序列定义为右子树,再递归定义即可得到一棵二叉树。
很多实际的问题都可以归结到Catalan 数,比如“买票找零问题”、“凸多边形三角划分”、“矩阵连乘的括号问题”等等,只要可以将问题归纳到这样的属性,即一个0和1必须成对的排列,而且1必须不能比0多,都可以归结为Catalan数。很多面试题都喜欢这种类型。