动态规划:不同的二叉搜索树

参考资料:代码随想录

题目链接:. - 力扣(LeetCode)

本题开始真的难到我了,看题解也很难理解,主要是涉及到了二叉树就很绕。跟随题解一步步思考,思路也就逐渐清晰,对动态规划也有了更清晰的认识。

1.确定dp数组含义

本道题的dp数组含义为,第i个下标代表由几个节点组成的二叉树,有几种方法。

以n=3为例,dp[0]代表0个节点的情况下,能组成几种二叉树。

d[1]代表1个节点下的情况,能组成几种二叉树。

dp[2]代表2个节点的情况下,能组成几种二叉树。

dp[3]代表3个节点的情况下,能组成几种二叉树。

2.初始化dp数组

本题的dp[0]初始化为1,可以理解为只有1才能推出正确结果,我不认同0个节点它也是二叉树,初始化为1完全就是能推出正确结果。

3.确定递推公式

以n=3为例,这几种二叉树大体上是由头节点1、2、3组成的,n=3的情况下,有几种二叉树等于头结点1的二叉树数量+头结点2的二叉树数量+头结点3的二叉树数量。

所以由此衍生出了一个变量"j",这个“j”就是控制头结点数值的。n为几那么j也就到几。所以递推公式初具雏形就是dp[i]+=xxx,这个+=的次数就是由头结点数量控制的。

那么具体的递推公式是什么,假设n=3,头结点j=1的话,头结点为1的二叉树数量=左子树数量*右子树数量,以此类推加3次,就得出了n个节点有几种二叉树了

4.确定遍历顺序

上述提到了,后面的的状态是依赖前面的状态推导出来的,所以是从前向后遍历。

class Solution {
    public int numTrees(int n) {
        //1.确定dp数组含义
        int[] dp = new int[n+1];
        //2.初始化dp数组
        dp[0] = 1;
        //3.确定遍历顺序
        for(int i = 1;i <= n;i++){
            for(int j = 1;j <= i;j++){
                //4.确定递推公式
                dp[i] += dp[j-1] * dp[i-j];
            }
        }
        return dp[n];
    }
}

 清晰的看出有n个节点时,有几种二叉树,且头结点为j时怎么组成的

public static void main(String[] args) {
        int n = 4;
        //1.确定dp数组含义
        int[] dp = new int[n+1];
        //2.初始化dp数组
        dp[0] = 1;
        //3.确定遍历顺序
        for(int i = 1;i <= n;i++){
            System.out.println("当n="+i+"时,一共有"+i+"个节点");
            for(int j = 1;j <= i;j++){
                //4.确定递推公式
                dp[i] += dp[j-1] * dp[i-j];
                int i1 = dp[j - 1] * dp[i - j];
                System.out.println("头结点为"+j+"时,有左子树数量"+dp[j-1]+"*右子树数量"+dp[i-j]+"="+ i1 +"种二叉树");
            }
        }
        System.out.println(Arrays.toString(dp));
        //return dp[n];
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值