不同的二叉搜索树

97 阅读2分钟

题目描述:

给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。

image.png

思考

  1. dp[n]:表示n个节点组成的二叉搜索树的种数
  2. 递推公式:
    1. 当n=1与n=2时:dp[1]=1,dp[2]=2 image.png
    2. 当n=3时: image.png dp[3]=元素1为头结点搜索树的数量 + 元素2为头结点搜索树的数量 + 元素3为头结点 搜索树的数量,其中:

元素1为头结点搜索树的数量 = 右⼦树有2个元素的搜索树数量 * 左⼦树有0个元素的搜索树数量

元素2为头结点搜索树的数量 = 右⼦树有1个元素的搜索树数量 * 左⼦树有1个元素的搜索树数量

元素3为头结点搜索树的数量 = 右⼦树有0个元素的搜索树数量 * 左⼦树有2个元素的搜索树数量

有2个元素的搜索树数量就是dp[2]。

有1个元素的搜索树数量就是dp[1]。

有0个元素的搜索树数量就是dp[0]。

所以dp[3] = dp[2] * dp[0] + dp[1] * dp[1] + dp[0] * dp[2]

image.png

在上⾯的分析中,其实已经看出其递推关系,dp[i] += dp[以j为头结点左⼦树节点数量] dp[以j为头结点右⼦树节点数量]

j相当于是头结点的元素,从1遍历到i为⽌

所以递推公式:dp[i] += dp[j - 1] * dp[i - j],j-1 为j为头结点左⼦树节点数量,i-j 为以j为 头结点右⼦树节点数量

  1. 初始化:dp[0]=1,空二叉树也是一种二叉树,推导的基础是dp[0]
  2. 遍历顺序:想要得到dp[i],得先得到dp[j-1],dp[i-j],故遍历顺序为,i=1至n,j=1至i
  3. 打印dp数组

代码

var numTrees = function(n) {
    //初始化
    var dp=new Array(n+1).fill(0);
    dp[0]=1;

    //根据递推公式得到dp数组
    for(let i=1;i<=n;i++){
        for(let j=1;j<=i;j++){
            dp[i]+=dp[j-1]*dp[i-j];
        }
    }
    
    return dp[n]
}

结果

image.png