每日LeetCode —— 96. 不同的二叉搜索树

69 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,点击查看活动详情

题目描述

       给定一个整n,求节点的值依次为 1 ~ n 的 n 个节点能够构成的二叉搜索树的种类 。

例1:输入:n=3  输出:5

1.png

解释:如上图所示,节点数为3可以构成以上五种情况的二叉搜索树。

原题地址:96. 不同的二叉搜索树

解题思路

       二叉搜索树即所有节点的值均大于其左边所有的节点,且均小于其右边所有的节点。

       本题只是求能够成二叉搜索树的种类数,而不是真正要构建二叉搜索树,在这里我们想是否可以得到一个可以快速求得种类数的方法呢。

       这里我们很容易的可以得到以下结论:

  • 当根节点的值确定后,其左边所有节点的值与右边所有节点的值都可以确定下来,如当n为4时,当要构建的二叉搜索树的根节点为3时,其左边的节点必定为1、2,右边的节点必定为4。进而左右节点的数即可以确定下来。
  • 当根节点确定的情况下,这种情况所能构成的二叉搜索树的种类就是左边节点所能构成的二叉搜索树的数目与右边节点所能构成二叉搜索树的数目相乘的结果。如n为4,根节点为3,其左边节点数为2,右边节点数为1,所有根节点为3的二叉搜索树有2*1 种。

       我们根据以上的结论可以构建dp[i]来存储节点数为i情况下所能构成的二叉搜索树的数目。初始情况下dp[0]=1,dp[1]=1,节点为0或1时二叉搜索树均只有1种。

例如我们例子中n为3,所有选定根节点后左右节点数的情况有以下三种:0个和2个、1个和1个、2个和0个。即dp[3]=dp[0]dp[2]+dp[1]dp[1]+dp[2]dp[0] dp[3]=dp[0]*dp[2] + dp[1]*dp[1] + dp[2]*dp[0]

实现代码

class Solution {
public:
    int numTrees(int n) {
        // 保存不同节点数的情况下可以形成的二叉搜索树的数目
        vector<int> dp(n+1,0);
        // 初始化节点数为0或1时二叉搜索树的数目为1
        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-j-1];
        }
        return dp[n];
    }
};