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

LeetCode 343 整数拆分

题目链接:https://leetcode.cn/problems/integer-break/

思路:

把一个数拆分成近似的m个数所得的乘积有可能最大

动规五部曲:

  1. dp[i]代表的是第i个数的最大乘积

  1. 递归公式:

可以想 dp[i]最大乘积是怎么得到的呢?

其实可以从1遍历j(j<i),然后有两种渠道得到dp[i].

一个是j * (i - j) 直接相乘。拆分成两个数

一个是j * dp[i - j],相当于是继续拆分(i - j),对这个拆分不理解的话,可以回想dp数组的定义。

j怎么就不拆分呢?

因为j是从1开始遍历,拆分j的情况,在遍历j的过程中其实都计算过了。那么从1遍历j,比较(i - j) * j和dp[i - j] * j 取最大的。

递推公式:dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));

那么在取最大值的时候,为什么还要比较dp[i]呢?

因为在递推公式推导的过程中,每次计算dp[i],要取最大值

  1. 初始化

显然,0和1不可以拆分,所以dp[0]和dp[1]都为0,dp[2]=1

  1. 遍历顺序

显然后面的数用到了前面的结果,所以是从前往后遍历。

  1. 打印数组

代码:

class Solution {
public:
    int integerBreak(int n) {
        vector<int>dp(n+1,0);
        dp[2] = 1;

        for(int i=3;i<=n;i++)
        {
            for(int j = 1;j<=i/2;j++)    // 因为拆分成近似的m个数才有可能乘积最大,如100,拆分成60和40必然小于拆分成50和50
            {
                dp[i] = max(dp[i],max(j*(i-j),j*dp[i-j]));
            }
        }
        return dp[n];
    }
};

总结

这个递推公式没想到。

LeetCode 96 不同的二叉搜索树

题目链接:https://leetcode.cn/problems/unique-binary-search-trees/

思路:

题解吧,详细。

代码:

class Solution {
public:
    int numTrees(int n) {
        vector<int>dp(n+1,0);
        dp[0] = 1;
        for(int i = 1;i<=n;i++)
        {
            for(int j = 1;j<=i;j++)
                dp[i]+=dp[j-1]*dp[i-j];
        }
        return dp[n];
    }
};

总结

想不到递归公式啊

今日总结:

有点类似数学的找规律题了,当初这方面就很差,只能死记硬背了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值