【动态规划】不同的二叉搜索树(手画图解)

        dp题的关键在于寻找状态转移方程。

目录

一、题目

二、确定dp数组含义及其下标含义

三、推导递推公式

四、确定如何初始化

五、确定遍历顺序

六、举例推导dp数组

七、代码实现

总结



一、题目

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

示例 1:

输入:n = 3
输出:5

示例 2:

输入:n = 1
输出:1

二、确定dp数组含义及其下标含义

        由题目可得,dp[i]的含义是:第i个节点组成且节点值从 1 到 i互不相同的 二叉搜索树 有dp[i]种。

三、推导递推公式

        

         从dp[3]可以看出:

        dp[3]的所有情况可以分为:

        左子树的根节点是2的所有情况 * 右子树的根节点是0的所有情况+

        左子树是的根节点1的所有情况 * 右子树的根节点是1的所有情况+

        左子树是的根节点0的所有情况 * 右子树是的根节点2的所有情况

        顺带验证一下dp[2]:

        左子树的根节点是1的所有情况 * 右子树的根节点是0的所有情况+

        左子树的根节点是0的所有情况 * 右子树的根节点是1的所有情况

        dp[1]:

        只够组成一个根节点,无法区分左右子树

        所以可以推导出:dp[i] += dp[以(j-1)为根节点的情况] * dp[以(i-j)为根节点的情况](j 从1遍历到i)

四、确定如何初始化

        由以上的分析可以知道,dp[1]由dp[0]得到,dp[2]由dp[1]+dp[0] + dp[0]+dp[1]得到,每个i由之前的i-1一直到0的所有dp[i]组成,所以只需要初始化一个dp[0] = 1。(认为空树有一个空结点)

五、确定遍历顺序

        由四可知,我们需要从前往后遍历才能得到经过计算的值。

六、举例推导dp数组

        

七、代码实现

class Solution {
public:
    int numTrees(int n) {
        vector<int> dp(n+1);
        dp[0] = 1;
        // 求以n为头节点的树个数
        for(int i = 1; i <= n; i++)
        {
            // 求以i为头节点的树个数
            for(int j = 1; j <= i; j++)
            {
                dp[i] += dp[j-1] * dp[i-j];
            }
        }
        return dp[n];
    }
};

总结

        这道题的难点在于递推公式的推导比较抽象,这就要求我们时刻记住第一步自己确定好的各种含义,在推导递推公式过程中,把握下一个状态是怎么能从上一个状态变化得到这一原则,勤加练习!

  • 12
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值