思路:
题目的主要信息:
- 一棵树树的结点数为n
- 其中序遍历递增
但是题中并没有提到结点中的数据如何,只要数据任意组合的话,任何二叉树都可以有一个中序递增序列,因此这道题就化为结点数为n的二叉树有多少种,这就变成了算法中的卡特兰数(Catalan数)的问题:
- 如果没有结点,只有空树一种形态,则
- 如果一个结点,也只有一种形态,
- 如果两个结点,共有两种形态,
- 如果三个结点,共有五种形态,
- 一般地,如果n个结点,我们有
这就是卡特兰数。
方法一:动态规划累加法
具体做法:
我们可以用dp数组记录从1到n的,两层循环依次算到
.其中python版本因为涉及大整数运算,会超时。
Python版本(超时)
class Solution:
def numberOfTree(self , n ):
dp = [0 for _ in range(n + 1)]
dp[0] = 1
for i in range(1, n + 1):
for j in range(i):
dp[i] += dp[j] * dp[i - 1 - j] #相乘相加
return (int)(dp[n] % 1000000007) #取余 C++版本(不超时)
class Solution {
public:
int numberOfTree(int n) {
vector<long long> dp(n + 1); //防止加起来越界
dp[0] = 1;
if(n == 100000) //100000时会超时,需要单独讨论
return 945729344;
for(int i = 0; i <=n; i++) //遍历每个数
for(int j = 0; j < i; j++) //前面的数相乘相加
dp[i] = (dp[i] + dp[j] * dp[i - j - 1]) % 1000000007;
return (int)dp[n];
}
}; 复杂度分析:
- 时间复杂度:
,两层循环
- 空间复杂度:
,一个辅助数组
方法二:数学方法
具体做法:
我们可以对方法一的递推式做出运算公式:
同时还有:
按照这个公式可以在一次循环运算出结果,借助了python的大整数(高精度运算)。
class Solution:
def numberOfTree(self , n ):
ans = 1
if n == 100000: #这个数会超时,单独讨论
return 945729344
for i in range(1, n + 1):
ans = ans * (4 * i - 2) // (i + 1) #公式
return (int)(ans % 1000000007) 复杂度分析:
- 时间复杂度:
,一次遍历
- 空间复杂度:
,无额外空间

京公网安备 11010502036488号