一、题目内容 中等

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

示例1:

5. 不同的二叉搜索树(96) - 图1 输入:n = 3 输出:5

示例2:

输入:n = 1 输出:1

提示:

  • 1 <= n <= 19

    二、解题思路

    我们先画画图,看能不能找到规律。从节点最少的开始画起。
    image.png
    n 为 1 的时候有一棵树,n 为 2 有两棵树,这个是很直观的。
    image.png
    当 1 为头节点的时候,我们可以发现 2、3 节点就是 n = 2 时的布局,dp[2]
    当 2 为头节点的时候,我们可以发现 1、3 节点就是 n = 1 时的布局,dp[1]
    当 3 为头节点的时候,我们可以发现 1、2 节点就是 n = 2 时的布局,dp[0]

    dp[3],就是 元素 1 为头结点搜索树的数量 + 元素 2 为头结点搜索树的数量 + 元素 3 为头结点搜索树的数量 元素 1 为头结点搜索树的数量 = 右子树有 2 个元素的搜索树数量 左子树有 0 个元素的搜索树数量 元素 2 为头结点搜索树的数量 = 右子树有 1 个元素的搜索树数量 左子树有 1 个元素的搜索树数量 元素 3 为头结点搜索树的数量 = 右子树有 0 个元素的搜索树数量 * 左子树有 2 个元素的搜索树数量

那么我们令 i 为节点数,dp[i]表示 i 个节点下,能形成的二叉搜索树个数。
初始化 dp[0] = 1、dp[1] = 1、dp[2] = 2
当 n = 3 时,dp[3]与之前 dp 的关系。
dp[3] = dp[2] * dp[0] + dp[1] * dp[1] + dp[0] * dp[2]
image.png
在上面的分析中,其实已经看出其递推关系,
dp[i] += dp[以j为头结点左子树节点数量] * dp[以j为头结点右子树节点数量]
所以递推公式:dp[i] += dp[j - 1] * dp[i - j]
j-1j为头结点左子树节点数量,i-j 为以j为头结点右子树节点数量)

三、具体代码

  1. /**
  2. * @param {number} n
  3. * @return {number}
  4. */
  5. var numTrees = function (n) {
  6. const dp = new Array(n + 1).fill(0);
  7. dp[0] = 1;
  8. for (let i = 1; i <= n; i++) {
  9. for (let j = 1; j <= i; j++) {
  10. dp[i] += (dp[j - 1] * dp[i - j])
  11. }
  12. }
  13. return dp[n]
  14. };
  15. /**
  16. * 时间复杂度:O(n^2)
  17. * 空间复杂度:O(n)
  18. */

四、其他解法