DP5 到底有多少个二叉搜索树

有多少个不同的二叉搜索树

原题链接

此题首先得明白什么是二叉搜索树(BST),二叉搜索树即这样的一种结构,每个结点存放一个值,这个结点为根的左子树上存放的值小于这个值,右子树存放的大于这个值,并且左右子树都是BST。

此题给出的条件确定了每个结点的值都是不相同的。

正因如此,1,2,3,4序列可组成的BST的个数和6,7,8,9可组成的BST的个数是一样的。

这能给我们什么启示呢?从本质上来说,6,7,8,9可以看做是1,2,3,4全体加5的结果。

全体加5并不会影响BST树是BST树。因此,上述两个序列可组成BST的个数是一样的。

那么对于一个1…n序列有多少种可能性呢?

由于值是互不相同的,因此所组成的BST的根结点的值只有n个。

因此,如果我们能计算出 根节点值相同的情况下可组成的BST的个数,再把这n种情况得到的结果相加,就能得到1…n序列可组成BST的总数。

又由于序列[1,…,n]和序列[m+1,…m+n]可组成的BST的总数是一样的。

所以如果我们去掉[1…n]序列中的根值m,根据BST的性质得到两个序列[1…m-1]和[m+1,…,n]。

定义dp[i] 为结点个数为i,总共可以组成BST的个数。

所以对于根植为m的可组成BST的总数为 dp[m-1]*dp[n-m]。

按相同的方式计算1-n中所有的结点,即可得到dp[n]。

#include <bits/stdc++.h>
using namespace std;
int main () {
    int n;
    scanf("%d", &n);
    vector<int> dp(n+1);//dp(i) 结点个数为i 总共可以组成 BST 的个数
    dp[0] = dp[1] = 1;//dp[0] 取1是为了之后相乘时不出现乘0结果为0的情况
    
    int left, right, sum;
    for(int i = 2; i <= n; ++i) {
        sum = 0;//计算结果初始化
        for(int j = 0; j < i; ++j) {//左边结点从0枚举到n-1 根的值从1到n
            left = j;//计算当前结点左边有的结点个数
            right = i - j - 1;//右边的结点个数
            sum += dp[left] * dp[right];//两个情况相乘
        }
        dp[i] = sum;//当前所有的可能性
    }
    printf("%d", dp[n]);
    return 0;
}

dp专题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值