云小杰

相对于绝对成功的汲汲渴求,越无杂质的奔赴,越是动人。

要一个黄昏, 满是风, 和正在落下的夕阳。如此, 足够我爱这破碎泥泞的人间。


Download the theme

不同的二叉搜索树

96. 不同的二叉搜索树

题目描述

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

实例1:

img

输入n = 3
输出5

示例 2:

输入:n = 1
输出:1

方法:动态规划

定义两个函数:

  1. $G(n)$:长度为 n 的序列能构成的不同二叉搜索树的个数。
  2. $F(i,n)$:以 i 为根、长度为 n 的不同二叉搜索树的个数($1<=i<=n$)。

可见,$G(n)$是我们求解需要的函数。

不同的二叉搜索树的总数 $G(n)$,是对所有 $i(i<=i<=n)$ 的 $F(i,n)$ 之和。 \(G(n)= \sum_{i=1}^{n}F(i,n)\) 当序列长度为 1(只有根)或为 0(空树)时, \(G(0)=1, G(1)=1\) 另外,根为 1 的所有二叉搜索树的集合是左子树集合和右子树集合的笛卡尔积.

举例而言,创建以 $3$ 为根、长度为 $7$ 的不同二叉搜索树,整个序列是 $[1, 2, 3, 4, 5, 6, 7]$,我们需要从左子序列 $[1, 2]$ 构建左子树,从右子序列 $[4, 5, 6, 7]$ 构建右子树,然后将它们组合(即笛卡尔积)。

对于这个例子,不同二叉搜索树的个数为$ F(3, 7)$。我们将 $[1,2]$ 构建不同左子树的数量表示为 $G(2)$, 从 $[4, 5, 6, 7]$ 构建不同右子树的数量表示为$ G(4)$,注意到 $G(n)$ 和序列的内容无关,只和序列的长度有关。于是,$F(3,7) = G(2) \cdot G(4)$。所以,我们可以得到以下公式: \(F(i,n) = G(i-1) \cdot G(n-1)\) 将公式$(1), (3)$结合可以得到: \(G(n) = \sum_{i=1}^{n}G(i-1) \cdot G(n-1)\) 至此,我们从小到大计算 $G$ 函数即可,因为 $G(n)$ 的值依赖于 $G(0) \cdots G(n-1)$。

    /**
     * 96. 不同的二叉搜索树
     *
     * @param n
     * @return
     */
    public int numTrees(int n) {
        int[] G = new int[n + 1];
        G[0] = 1;
        G[1] = 1;
        for (int i = 2; i <= n; i++) {
            for (int j = 1; j <= i; j++) {
                G[i] += G[j - 1] * G[i - j];
            }
        }
        return G[n];
    }
最近的文章

买卖股票

买卖股票121. 买卖股票的最佳时机题目说明给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。实例1输入:[7,1,5,3,6,4]输出:5解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 =...…

继续阅读
更早的文章

Swagger

Swagger1. 引言​ 相信无论是前端还是后端开发,都或多或少地被接口文档折磨过。前端经常抱怨后端给的接口文档和实际情况不一致。后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新。其实无论是前端调用后端,还是后端调用前端,都期望有一个好的接口文档。但是这个接口文档对于程序员来说,就跟注释一样,经常还会抱怨别人写的代码没有写注释,然而自己写起代码来,最讨厌的也是写注释。所以仅仅只听过强制了来规范大家是不够的,随着时间推移,版本迭代,接口文档往往很容易就跟不上代码了。2. 什么是...…

继续阅读