Leetcode:96. 不同的二叉搜索树
Leetcode:96. 不同的二叉搜索树
题目在链接中,点进去看看吧!
先介绍一个名词:卡特兰数
卡特兰数
卡特兰数Cn满足以下递推关系:
[C_{n+1}=C_0C_n+C_1C_{n-1}+...+C_nC_0
]
很巧的是,这道题可以利用亚特兰数计算出有多少个不同的BST。
Don't talk,show me code!
class Solution {
public:
int numTrees(int n) {
vector<int> dp(n+2);
dp[0]=1;
for(int i=1;i<=n;i++){
int temp=i-1;
while(temp>=0){
dp[i]+=dp[temp]*dp[i-temp-1];
temp--;
}
}
return dp[n];
}
};
简单分析
这道题利用的是动态规划的思想,递推得出一个dp数组。在找规律的过程中,我们意外发现这道题的答案与亚特兰数的数学递推式和dp方程完全一致!
前提条件:这是一颗BST树,中序遍历得出的排列等于其升序排列
-
首先,当结点数为0时,树的个数为1
-
分析当结点数为1时:
- 取1为根节点,则左子树的结点数为0,右子树的结点数为0
- 因此结点数为1的左右子树情况为(1*1=1)
-
分析当结点数为2时:
- 取1为根节点,则左子树的结点数为0,右子树的结点数为1
- 因此1根节点所有可能出现的树情况为(1*1=1)
- 取2为根节点,则左子树的结点数为1,右子树的结点数为0
- 因此2根节点所有可能出现的树情况为(1*1=1)
- 因此结点数为2的左右子树情况为(1+1=2)
-
分析当结点数为3时:
- 取1为根节点,则左子树的结点数为0,右子树的结点数为2
- 因此1根节点所有可能出现的树情况为(1*2=2)
- 取2为根节点,则左子树的结点数为1,右子树的结点数为1
- 因此2根节点所有可能出现的树情况为(1*1=1)
- 取2为根节点,则左子树的结点数为2,右子树的结点数为0
- 因此3根节点所有可能出现的树情况为(2*1=2)
- 因此结点数为3的左右子树情况为(1+2+1=5)
-
有兴趣可以继续递推,总之总结规律:
[dp[k]=sum_0^{k-1} dp[i]*dp[k-i-1] ] -
然后就是编程实现啦~