不同的二叉查找树
给出 n,问由 1…n 为节点组成的不同的二叉查找树有多少种?
样例 1:
输入:
n = 3
输出:
5
解释:
有5种不同形态的二叉查找树
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
解答:
定义dp[i] 为当节点数为i时,二叉查找树的种类数
看如下规律:
当节点为0时:dp[0] = 1
当节点为1时:dp[1] = 1
当节点为2时:dp[2] = dp[1] + dp[1] = 2
当节点为3时:dp[3] = dp[2] + dp[1] * dp[1] + dp[2] = 5
当节点为4时:dp[4] = dp[3] + dp[1] * dp[2] + dp[2] * dp[1] + dp[3] = 14
当节点为5时:dp[5] = dp[4] + dp[1] * dp[3] + dp[2] * dp[2] + dp[3] * dp[1] + dp[4] = 42
…
以上是何意呢?
举一个例子,假设节点为4,每一个节点都有成为根节点的机会:
当节点1为根节点时,左子树是0个节点,右子树是3个节点,左子树0个节点的表现形式有dp[0]种,右子树3个节点的表现形式有dp[3]种,左右组合则有dp[0] * dp[3]种
当节点2为根节点时,左子树是1个节点,右子树是2个节点,左子树1个节点的表现形式有dp[1]种,右子树2个节点的表现形式有dp[2]种,左右组合则有dp[1] * dp[2]种
当节点3为根节点时,左子树是2个节点,右子树是1个节点,左子树2个节点的表现形式有dp[2]种,右子树1个节点的表现形式有dp[1]种,左右组合则有dp[2] * dp[1]种
当节点4为根节点时,左子树是3个节点,右子树是0个节点,左子树3个节点的表现形式有dp[3]种,右子树0个节点的表现形式有dp[0]种,左右组合则有dp[3] * dp[0]种
故状态转换方程为:
dp[i] = dp[0]*dp[i] + dp[1]*dp[i-1] + … + dp[i-1]*dp[1] + dp[i]*dp[0];
可在运算过程优化,计算前半段乘以2即可
class Solution {
public:
/**
* @param n: An integer
* @return: An integer
*/
int numTrees(int n) {
// write your code here
/*
定义dp[i] 为当节点数为i时,二叉查找树的种类数
看如下规律:
当节点为0时:dp[0] = 1
当节点为1时:dp[1] = 1
当节点为2时:dp[2] = dp[1] + dp[1] = 2
当节点为3时:dp[3] = dp[2] + dp[1] * dp[1] + dp[2] = 5
当节点为4时:dp[4] = dp[3] + dp[1] * dp[2] + dp[2] * dp[1] + dp[3] = 14
当节点为5时:dp[5] = dp[4] + dp[1] * dp[3] + dp[2] * dp[2] + dp[3] * dp[1] + dp[4] = 42
...
以上是何意呢?
举一个例子,假设节点为4,每一个节点都有成为根节点的机会:
当节点1为根节点时,左子树是0个节点,右子树是3个节点,左子树0个节点的表现形式有dp[0]种,右子树3个节点的表现形式有dp[3]种,左右组合则有dp[0] * dp[3]种
当节点2为根节点时,左子树是1个节点,右子树是2个节点,左子树1个节点的表现形式有dp[1]种,右子树2个节点的表现形式有dp[2]种,左右组合则有dp[1] * dp[2]种
当节点3为根节点时,左子树是2个节点,右子树是1个节点,左子树2个节点的表现形式有dp[2]种,右子树1个节点的表现形式有dp[1]种,左右组合则有dp[2] * dp[1]种
当节点4为根节点时,左子树是3个节点,右子树是0个节点,左子树3个节点的表现形式有dp[3]种,右子树0个节点的表现形式有dp[0]种,左右组合则有dp[3] * dp[0]种
故状态转换方程为:
dp[i] = dp[0]*dp[i] + dp[1]*dp[i-1] + ... + dp[i-1]*dp[1] + dp[i]*dp[0];
可在运算过程优化,计算前半段乘以2即可。
*/
int m = n + 1;
int *dp = new int[m];
for (int i = 0; i < m; i++) {
dp[i] = 0;
}
dp[0] = 1;
dp[1] = 1;
for (int i = 2; i < m; i++) {
for (int j = 0; j < i; j++) {
dp[i] += (dp[j] * dp[i - j - 1]);
}
}
int nRet = dp[n];
delete[] dp;
return nRet;
}
};