96. 不同的二叉搜索树
给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?
示例:
输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3
方法一:动态规划
代码:
1 class Solution { 2 public: 3 int numTrees(int n) { 4 if(n == 0 || n == 1) return n; 5 vector<int> a(n + 1,0); 6 a[0] = 1, a[1] = 1; 7 for(int i = 2;i <= n;++i){ 8 for(int j = 1;j <= i;++j) { 9 a[i] += a[i-j]*a[j-1]; 10 } 11 } 12 return a[n]; 13 } 14 };
思路:可怜的我完全没有思路。最后这里还是要感谢官方题解。这里我用自己的语言来复述一些官方动归的思路。
为了便于推导出递推公式,需要借助两个函数:
G(n):长度为n的整数能生成的二叉树的种类
F(i,n):以i为根的二叉树的种类,其中(1≤i≤n)
那么应当有\[G(n) = \sum\limits_{i = 1}^n {F(i,n)} \]
。因为以i为根则生成的二叉树不同,所以最后G(n)可以看成是以i(1≤i≤n)为根的所有类型二叉树种类的和。
对于F(i,n),其所能生产的二叉树种类可以看成子问题(1,i-1)和(i+1,n)两部分组成的种类的积。
所以\[F(i,n) = G(i - 1)G(n - i)\],因此可以求出递推方程\[G(n) = \sum\limits_{i = 1}^n {G(i - 1)G(n - i)}\]。
分析:最后时间复杂度为O(n2),空间复杂度O(n)。
方法二:数学演绎法
其实这里的G(n)就是所谓的卡特兰数,因此可以用通项公式直接求出来,这里采用了递推公式
\[{C_0} = 1,{C_{n + 1}} = \frac{{2(2n + 1)}}{{n + 2}}{C_n}\]
可以直接推导出结果。
代码:
1 class Solution { 2 public: 3 int numTrees(int n) { 4 int c = 1; 5 for(int i = 1;i<n;++i){ 6 c *=2*(2*n+1)/(n+2); 7 } 8 return c; 9 } 10 };
结论:时间复杂度为O(n),空间复杂度O(1)。
写在最后:卡特兰数虽然有通项公式
\[{C_n} = \frac{1}{{n + 1}}C_{2n}^n\]
但是求解起来并不简单啊,还不如乖乖地推。