力扣96.不同的二叉搜索树

题目:

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

示例一:

输入:n = 3
输出:5

示例二:

输入:n = 1
输出:1

提示:

  • 1 <= n <= 19

思路:

这道题使用了动态规划的dp数组来解决问题,想要先思考这道题的dp数组是什么含义。

这道题的dp数组含义为结点为i时能够构成二叉搜索树的个数。

然后我们可以想到结点个数分别为1和2时能够组成的二插搜索树的个数分别为1和2,之后我们就可以去想之后的dp数组应该如何去计算。

这里我们通过下面着段代码去计算后面的dp数组

dp[i] += dp[j - 1] * dp[i - j];

其中的i为结点个数,j为此时的根节点,因为这道题计算的时二叉搜索树,所以当我们确定以谁为根节点时,左右子树的个数都可以确定下来

左子树结点个数为(j - 1)

右子树结点个数为(i - j)

这样我们就能解决这道题目,但是在后面计算的过程中我们会发现两个特殊情况:

1.dp[0]该赋值为什么

因为有一些情况下确实会出现dp[0]去乘以一个数字来计算,所以我们将dp[0]赋值为1,这样就可以解决这个问题,

2.n = 1时的越界问题

若此时n = 1时,我们在赋值dp[2]时会发生越界问题,对于这种情况,我们有两种解决方法,第一种是单独写一条判断语句来解决,第二种就是将所以的下标向前移动一位,即结点个数为1时代表dp[0],结点个数为2时代表dp[1],这样也可以解决这个问题

代码:

class Solution {
public:
    int numTrees(int n) {
        //dp[i]表示结点为i时能够组成二插搜素树的个数
        if(n == 1){//因为我们在循环前赋值时赋值到了dp[2],所以我们想要判断n=1的情况,不然会跃界
            return 1;
        }
        vector<int> dp(n + 1);//范围开到n + 1的原因是为了包括结点个数为n时的情况
        dp[0] = 1;//因为后面我们想要使用乘法来完成当前根结点组成二叉树的情况,所以我们想要将dp[0]赋值为1
        dp[1] = 1;
        dp[2] = 2;
        for(int i = 3; i <= n; i++){
            //确定根节点为谁,就能确定左子树结点个数(j - 1)与右子树结点个数(i - j)
            for(int j = 1; j <= i; j++){//以j为根结点
                dp[i] += dp[j - 1] * dp[i - j];
            }
        }
        return dp[n];
    }
};

时间复杂度:O(n^{2})

n为结点个数

空间复杂度:O(n)

额外使用n+1的空间来存放数据,但是空间复杂度不是O(n + 1),而是O(n),

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

puzell

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值