不同的二叉搜索树I@96.leetcode

不说废话,直戳盲点,打通思路, 举一反三。

题目描述

给定一个整数 n,求以 1 … n 为节点组成的二叉搜索树有多少种?

输入: 3
输出: 5
解释:
给定 n = 3, 一共有 5 种不同结构的二叉搜索树:

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-binary-search-trees

先上代码

执行用时 :4 ms, 在所有 C++ 提交中击败了89.08%的用户
内存消耗 :8.2 MB, 在所有 C++ 提交中击败了57.19%的用户

class Solution {
public:

    int numTrees(int n) {
        if(n == 0)
            return 0;
        vector<int> dp(n+1);
        dp[0] = 1;
        dp[1] = 1;
        for(int i=2;i<=n;++i){
            for(int index = 1; index <=i; ++index){
                dp[i] += dp[index-1] * dp[i-index];
            }
        }
        return dp[n];
    }
};

算法思路

是一个动态规划问题, 使用诸如递归等方式会导致超时。

  1. d p ( n ) dp(n) dp(n)表示输入为n时,有多少种不同的二叉搜索树。易知: d p ( 1 ) = 1 dp(1)=1 dp(1)=1
  2. f n ( i ) f_n(i) fn(i)表示当输入为n时,以 i 作为根,有多少种不同的二叉搜索树。
  3. 那么,我们很容易得到下面的等式: (1) d p ( n ) = f n ( 1 ) + f n ( 2 ) + . . . + f n ( n ) dp(n) = f_n(1) + f_n(2)+...+f_n(n)\tag{1} dp(n)=fn(1)+fn(2)+...+fn(n)(1)
  4. 而当输入为n,以 i 作为根时,不同的二叉搜索树的种类数量等于左子树的种类数目乘右子树的种类数目,即: (2) f n ( i ) = d p ( i − 1 ) ∗ d p ( n − i ) f_n(i) = dp(i-1)*dp(n-i)\tag{2} fn(i)=dp(i1)dp(ni)(2) 这里,由于生成二叉搜索树的种类只与有序数列中数字的种类数目有关,而与数字的大小无关,所以 i+1, i+2,…,n 这组数生成的二叉搜索树的种类数目与 1,2,…,n-i 生成的二叉搜索树种类数目相同,所以后半部分直接用 d p ( n − i ) dp(n-i) dp(ni)表示。
  5. 由(1)式和(2)式,我们可以得到下面的结论: d p ( n ) = d p ( 0 ) ∗ d p ( n − 1 ) + d p ( 1 ) ∗ d p ( n − 2 ) + . . . + d p ( n − 1 ) ∗ d p ( 0 ) dp(n) = dp(0)*dp(n-1) + dp(1)*dp(n-2)+...+dp(n-1)*dp(0) dp(n)=dp(0)dp(n1)+dp(1)dp(n2)+...+dp(n1)dp(0) (3) d p ( n ) = ∑ i = 1 n d p ( i − 1 ) ∗ d p ( n − i ) dp(n) = \sum_{i=1}^{n}dp(i-1)*dp(n-i)\tag{3} dp(n)=i=1ndp(i1)dp(ni)(3)
  6. 有了(3)式作为理论基础,我们可以使用动态规划的方式去解决上面的问题。而且,我们必须将 d p ( 0 ) dp(0) dp(0)设置为1(想想为什么?).

学习和思考

  • 在这个问题中,很难一下子得到一个动态规划的状态转移方程。要学会通过问题分解,分别解决而后整合公式的方式,建模一个动态规划问题并且解决。
  • 如果需要得到不同种类的二叉搜索树具体是什么,该怎么办? 参考不同的不同的二叉搜索树II
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值