# [96. Unique Binary Search Trees](https://leetcode.com/problems/unique-binary-search-trees/)

# 思路
由节点1,2,...,n可以组成多少棵二叉搜索树。         
先来看看二叉搜索树的定义。它或者是一棵空树，或者是具有下列性质的二叉树： 
* 若它的左子树不空，则左子树上所有结点的值均小于它的根结点的值； 
* 若它的右子树不空，则右子树上所有结点的值均大于它的根结点的值； 
* 它的左、右子树也分别为二叉排序树。

## 思路一、动归
先来看一个例子，当n=3时:
```
 1               1                   2                    3             3
  \               \                /   \                 /             / 
   3               2              1     3               2             1
  /                 \                                  /               \
 2                   3                                1                 2
 ```

我们可以看到，以1为根的树有几个，完全取决于有二个元素的子树有几种。同理，以2为根的子树取决于一个元素的子树有几个。以3为根的情况，则与1相同。

定义`dp[i]`为用1,2,...,i能构成Unique Binary Tree的数目，特别的`dp[0] = dp[1] = 1`。

如果数组有两个元素{1,2}， 那么有如下两种可能
```
1                    2
 \                  /
  2                1
```
即
```
dp[2] = dp[0] * dp[1]  (1为根的情况)
      + dp[1] * dp[0]  (2为根的情况)
```

再看一遍三个元素的数组，可以发现BST的取值方式如下：
```
dp[3] = dp[0]*dp[2]  (1为根的情况)
      + dp[1]*dp[1]  (2为根的情况)
      + dp[2]*dp[0]  (3为根的情况)
```

所以，由此观察，可以得出递推公式为
```
dp[i] =  dp[0]*dp[i-1] + dp[1]*dp[i-2] + ... + dp[i-1]*dp[0]
```

## 思路二
我们知道前序遍历序列和中序遍历序列可以确定唯一一颗二叉树，中序遍历是递增的即1,2,...n的话一定是二叉搜索树，所以问题可以转换成给定中序序列，有多少种可能的前序序列？
根据中序和前序的递归算法，这个问题等价于给定进栈顺序，有多少种出栈的顺序。答案就是卡特兰数，即`C(2n,n) / (n + 1)`。所以我们可以直接计算这个值。

# C++
## 思路一
``` C++
class Solution {
public:
    int numTrees(int n) {        
        vector<int>dp(n + 1, 0);
        dp[0] = 1;
        dp[1] = 1;
        for(int i = 2; i <= n; i++)
            for(int j = 0; j < i; j++) dp[i] += dp[j]*dp[i - 1 - j];
        
        return dp[n];
    }
};
```

## 思路二
``` C++
class Solution {
public:
    int numTrees(int n) {
        long long res = 1, tmp = 1; // 注意用long long
        for(int i = 1; i <= n; i++){
            res *= (2 * n - i + 1);
            if(res % i == 0) res /= i;
            else tmp *= i;
            if(res % tmp == 0){
                res /= tmp;
                tmp = 1;
            }
            
        }
        return int((res / tmp) / (n + 1));
    }
};
```
