LeetCode 👉 HOT 100 👉 不同的二叉搜索树 - 简单题

135 阅读3分钟

「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。

题目

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

示例1

输入:n = 3

输出:5

示例2

输入:n = 1

输出:1

思路

如果不理解什么是 二叉搜索树,这道题压根就没法解,先复习一下:

首先 二叉树 的概念为:每一个节点都拥有左右两个节点;而 二叉搜索树,还需要满足另外一个条件,就是所有的左节点的数字都比父节点的数字小,右节点的数字都比父节点的数字大。

那么如何去构建一颗 二叉搜索树 呢?比如,对于数字序列 [1, 2, 3],如果将 1 作为根节点,则左子树应该为空,因为找不到比 1 还小的数字了,同时剩下的 [2, 3] 则成为右子树;那么由 [2, 3] 构成的右子树同样也必须是 二叉搜索树,则可以由 2 作为根节点,3 则是右节点;或由 3 作为根节点,则 2 成为左节点。同样的情况,可以依次以 2, 3 作为第一次的根节点,分别去构建 二叉搜索树;

其实上述的例子,就是三个有序的数字,能形成的二叉树的总数;注意这三个有序数字,并不特指 [1, 2, 3],只要是有序的三个数,能够生成的 二叉搜索树 的总数情况都是一样的。

那么可以用 动态规划 解决这道题:

  • 定义 dp[i]i 个有序数字,能形成的 二叉搜索树 的数量

  • 则有 dp[0] = 1; dp[1] = 1,即空树也算一个二叉搜索树,当只有一个数字时,也只能形成一种树

对于递归公式,从上面的例子 [1, 2, 3],可以发现 dp[3] 会等于分别以 1, 2, 3 为根节点形成的 二叉搜索树 的数量相加;那么对于两个有序的数字 [2, 3],即 dp[2], 会等于分别以 2, 3 为根节点形成的 二叉搜索树 的数量相加,同时我们有 dp[0] = 1, dp[1] = 1;

动态规划完整代码


    /**
     * @param {number} n
     * @return {number}
     */
    var numTrees = function (n) {
        const dp = new Array(n + 1).fill(0);

        dp[0] = 1;
        dp[1] = 1;

        // 计算 i 个有序数字形成的 二叉搜索树的数量
        for(let i = 2; i <= n; i++) {
            // 计算以 j 为根节点,形成的二叉搜索树
            for(let j = 1; j <= i; j++) {
                dp[i] += dp[j - 1] * dp[i - j];
            }
        }

        return dp[n];
    };

小结

Get 新知识,什么是 二叉搜索树,如何基于一个有序数列,去构建 二叉搜索树

知识在于积累,总有用上的那一天。

LeetCode 👉 HOT 100 👉 不同的二叉搜索树 - 中等题

合集:LeetCode 👉 HOT 100,有空就会更新,大家多多支持,点个赞👍

如果大家有好的解法,或者发现本文理解不对的地方,欢迎留言评论 😄