不同的二叉搜索树 I
题目描述
给定一个整数 n,求以 1 … n 为节点组成的二叉搜索树有多少种?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-binary-search-trees
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
一、卡特兰数
长度为n的序列不同二叉搜索树的个数称为卡特兰数。卡特兰数更便于计算的定义如下:(避免阶乘运算(
C
(
n
)
=
1
n
+
1
C
2
n
n
C(n)=\dfrac{1}{n+1}C_{2n}^n
C(n)=n+11C2nn))
C
0
=
1
C_0=1
C0=1,
C
n
+
1
=
2
(
2
n
+
1
)
n
+
2
C
n
C_{n+1}=\dfrac{2(2n+1)}{n+2}C_n
Cn+1=n+22(2n+1)Cn
根据此递推公式,有如下代码
代码(c++)
class Solution {
public:
int numTrees(int n) {
long long temp=1;
for(int i=0;i<n;i++){
temp=temp*2*(2*i+1)/(i+2);
}
return int(temp);
}
};
二、动态规划
求有序序列1…n构成不同二叉搜索树的总数,就是以序列中每个元素为根结点,左右两个子序列为左右子树构成的不同二叉搜索树的总数。子序列又重复这一过程。
定义两个函数:
G
(
n
)
G(n)
G(n):长度为n的序列不同二叉搜索树的个数
F
(
i
,
n
)
F(i,n)
F(i,n):以i为根结点的不同二叉搜索树个数
长度为n的序列不同二叉搜索树的总数是以其中每个元素为根得到的不同二叉搜索树的总数,所以有
G
(
n
)
=
∑
i
=
1
n
F
(
i
,
n
)
(
1
)
G(n)=\sum\limits_{i=1}^{n}F(i,n) ~~~~~~~~~~(1)
G(n)=i=1∑nF(i,n) (1)
对于边界情况,当序列长度为 1 (只有根)或为 0 (空树)时,只有一种情况。亦即:
G
(
0
)
=
1
,
G
(
1
)
=
1
G(0)=1, G(1)=1
G(0)=1,G(1)=1
以i为根结点的不同二叉搜索树个数
F
(
i
,
n
)
F(i,n)
F(i,n)是左右子树个数的笛卡尔积,即两个子序列组合总数等于两个子序列长度的乘积,如下图所示:
于是有
F
(
i
,
n
)
=
G
(
i
−
1
)
⋅
G
(
n
−
i
)
(
2
)
F(i,n)=G(i-1)\cdotp G(n-i)~~~~~~~~~~(2)
F(i,n)=G(i−1)⋅G(n−i) (2)
结合(1)(2)可得递推式子:
G
(
n
)
=
∑
i
=
1
n
G
(
i
−
1
)
⋅
G
(
n
−
i
)
(
3
)
G(n)=\sum\limits_{i=1}^{n}G(i-1)\cdotp G(n-i) ~~~~~~~~~~(3)
G(n)=i=1∑nG(i−1)⋅G(n−i) (3)
代码(c++)
class Solution {
public:
int numTrees(int n) {
vector<int> G(n+1,0);
G[0]=1;
G[1]=1;
for(int i=2;i<=n;i++){
for(int j=1;j<=i;j++){
G[i]+=G[j-1]*G[i-j];
}
}
return G[n];
}
};
不同的二叉搜索树 II
题目描述
给定一个整数 n,生成所有由 1 … n 为节点所组成的二叉搜索树。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-binary-search-trees-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
递归查找:
以当前序列中的每一个元素为根结点,将序列分成左右两个子序列,分别是当前根结点的左右子树序列,以同样的方法递归的搜索每个子序列中所有不同的二叉搜索树,最后递归返回到该层,将左右两个子序列中的所有二叉搜索树组合构成当前根结点的左右子树,并保存在当前递归层存储不同二叉树的容器中,以作为上一层根结点的左或右子树。
可以用一个map记录出现过的子树序列,避免重复查找。以序列左右端点构成的pair作为键,序列作为值。
代码(c++)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<TreeNode*> find_search(map<pair<int,int>,vector<TreeNode*> > &mp,int left,int right){
vector<TreeNode*> layer;
if(left>right){
layer.push_back(NULL);
return layer;
}
if(left==right){
TreeNode* temp=new TreeNode(left);
layer.push_back(temp);
return layer;
}
if(mp.find(make_pair(left,right))!=mp.end()) return mp[make_pair(left,right)];
for(int i=left;i<=right;i++){
vector<TreeNode*> l=find_search(mp,left,i-1);
vector<TreeNode*> r=find_search(mp,i+1,right);
for(int j=0;j<l.size();j++){
for(int k=0;k<r.size();k++){
TreeNode* temp=new TreeNode(i);
temp->left=l[j];
temp->right=r[k];
layer.push_back(temp);
}
}
mp[make_pair(left,right)]=layer;
}
return layer;
}
vector<TreeNode*> generateTrees(int n) {
vector<TreeNode*> res;
if(n==0) return res;
map<pair<int,int>,vector<TreeNode*> > mp;
int left=1,right=n;
res=find_search(mp,left,right);
return res;
}
};