代码随想录算法训练营第四十一天|343. 整数拆分 、96.不同的二叉搜索树

文章介绍了使用动态规划方法解决LeetCode上的两道问题:343.整数拆分和96.不同的二叉搜索树。关键在于理解递推公式,通过构建dp数组,计算不同情况下整数拆分的最大乘积和不同节点数量的二叉搜索树的组合数。
摘要由CSDN通过智能技术生成

目录

343. 整数拆分

96.不同的二叉搜索树


343. 整数拆分

代码随想录

题解思路:

题目还是动态规划的常规题目,使用n+1数组保存0-n范围内正整数拆分后的最大值,这里最大值的取法需要注意,要考虑三种情况:
1、拆成两个数的情况:12 , 21
2、拆成三个数(dp[i]至少会拆分成两个数)及以上的情况:dp[3]就是看dp[2]*1、dp[1]*2 ,dp[4]就是看dp[3]*1、dp[2]*2、dp[1]*3
3、还有就是要保持dp[3]要最大,只有拆分比当前dp[3]大的时候,此时才更新dp[3]

class Solution {
    public int integerBreak(int n) {
        //动规第一步:确定dp[i]的含义:整数i拆分后得到的乘积最大值
        //动规第二步:确定递推公式:这里其实还是依赖上一个数拆分后取得的最大值,比如dp[3]最大值就是看
            //拆成两个数的情况:1*2 , 2*1
            //拆成三个数(dp[i]至少会拆分成两个数)及以上的情况:dp[3]就是看dp[2]*1、dp[1]*2 ,dp[4]就是看dp[3]*1、dp[2]*2、dp[1]*3
            //还有就是要保持dp[3]要最大,只有拆分比当前dp[3]大的时候,此时才更新dp[3]
            //综合上述三点其递推公式为:dp[i] = Math.max{ (i - j)*j, dp[i-j]*j, dp[i]}
        //动规第三步:初始化dp数组:dp[1] = 0 dp[2] = 1
        //动规第四步:确定遍历顺序:从前往后遍历
        //动规第五步:打印dp数组
        int[] dp = new int[n+1];
        dp[0] = 0;
        dp[1] = 0;
        dp[2] = 1;
        for(int i = 3; i < dp.length; i++){
            for(int j = 1; j < i; j++){
                dp[i] = Math.max(Math.max((i - j)*j, dp[i-j]*j), dp[i]); //Math.max(a,b)只能两者比较取其一
            }
        }
        return dp[dp.length-1];
    }
}

题解思路:

依然是动态规划的常规题,跟着卡哥按部就班刷下来确实有点感觉了,想知道输入n后,即有n个节点一共有多少种不同二叉搜素树的个数,还是得依赖于有n-1个节点时构成的二叉搜索树的个数,但是需要考虑左右子树在不同的节点个数情况下的排列组合,具体说明见代码注释!!!

class Solution {
    public int numTrees(int n) {
        //确定dp[i]的含义:输入i,也就是i个节点组成二叉搜索树的种树
        int[] dp = new int[n+1];
        dp[0] = 1;
        dp[1] = 1;
        if(n > 1) dp[2] = 2;
        for(int i = 3; i < n + 1; i++){ //控制dp数组的下标dp[i]
            for(int j = 1; j <= i; j++){  //控制头节点的值,根据二叉搜索树的特性,左子树的值 < 根节点的值 < 右子树的值,则根节点的值-1 = 左子树的节点个数, i-根节点的值 = 右子树的节点个数
                dp[i] += dp[j - 1] * dp[i - j]; //dp[i-1]:就是左子树有i-1个节点时,总共有dp[i-1]种不同的二叉树
                                                //dp[i -j]:就是右子树有j-i个节点时,总共有dp[i-j]种不同的二叉树
                                                //对左右二叉树的个数排列组合就是相乘得到总的
            }
        }
        return dp[n];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值