mirror of
https://github.com/ShusenTang/LeetCode.git
synced 2024-09-02 14:20:01 +00:00
Create 96. Unique Binary Search Trees.md
This commit is contained in:
parent
877ba71620
commit
cc082766a1
88
solutions/96. Unique Binary Search Trees.md
Normal file
88
solutions/96. Unique Binary Search Trees.md
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
# [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));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
Loading…
Reference in New Issue
Block a user