思路:

题目的主要信息:

  • 一棵树树的结点数为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)

复杂度分析:

  • 时间复杂度:,一次遍历
  • 空间复杂度:,无额外空间