算法:不同的二叉搜索树

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

一、背景介绍

二、解题思路

总结


提示:以下是本篇文章正文内容,下面案例可供参考

一、背景介绍

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

输入:n = 3

输出:5

根节点分别为1、2、3时,一共有五种情况,分别是

1)根节点为1,先给节点2,再给节点3

2)根节点为1,先给节点3,再给节点2

3)根节点为2,分别给节点1和3

4)根节点为3,先给节点1,再给节点2

5)根节点为3,先给节点2,再给节点1

输入:n = 1

输出:1

二、解题思路

假设我们有一个由 i 个节点组成的二叉搜索树,我们选择其中一个节点作为根节点。设根节点的值为 j,那么:

左子树将包含小于 j 的所有节点,即 1 到 j-1 的节点,因此左子树有 j-1 个节点

右子树将包含大于 j 的所有节点,即 j+1 到 i 的节点,因此右子树有 i-j 个节点

由于二叉搜索树的性质,左子树和右子树也必须是二叉搜索树。因此,左子树的种数为 dp[j-1],右子树的种数为 dp[i-j]

这个地方有点儿绕,突然就从二叉树跳跃到数组值了,解释一下是怎么来的。

这个地方需要转换一下思路,就把j-1当成j-1个节点的组合数,i-j当成i-j个节点的组合数,举个例子,例如j为2时,左子树一共有2-1=1个节点,那么组合方式就是1;例如j为3时,左子树一共有3-1=2个节点,那么组合方式就是2,依此类推。就把它当作从1开始的几个数,然后自由组合。

所以我们并不是在求指定的一些数字的组合,而是转变为求几个从1开始的数字的组合,这么看就简单多了。

刚好这些组合数是我们前边已经计算过的,所以直接利用。

代码示例:

public void test() {
    int n = 3;
    int[] dp = new int[n + 1];
    // 初始化0个节点和1个节点的组合数
    dp[0] = dp[1] = 1;
    // 从2个节点开始计算
    for (int i = 2; i <= n; i++) {
        // j为左子树节点数, 由于根节点需要占一个位置, 所以j的取值范围是0到i-1
        for (int j = 0; j < i; j++)
            // 计算组合数, 累计不同的根节点情况下, 所有左右子树的组合数
            dp[i] += dp[j] * dp[i - j - 1];
    }
    System.out.println(JSON.toJSONString(dp));
}

这个题目的关键点就是思路的切换。


总结

每天进步一点点!

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值