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

文章讲述了如何使用递推法解决整数拆分问题,通过构建dp数组并推导出递推公式,以及如何计算n个节点的二叉搜索树数量。重点在于理解递推公式的由来和遍历过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

343.整数拆分

题目链接/文章讲解/视频讲解:代码随想录

1.代码展现

//343整数拆分
int integerBreak(int n) {
	//step1 构建dp数组,确定dp[i]的含义
	//dp[i]的含义是i被拆分后的积的最大值
	vector<int> dp(n + 1, 0);
	//step2 确定递推公式
	//dp[i] = max(dp[i], max(j * (i - j), j * dp(i - j)))
	//step3 dp初始化,dp[0], dp[1]初始化没有意义,不能被拆分成正整数
	//根据递推公式,只需要初始化dp[2]
	dp[2] = 1;
	//step4 遍历
	for (int i = 3; i <= n; i++) {
		for (int j = 1; j < i; j++) {
			dp[i] = max(dp[i], max(dp[i - j] * j, (i - j) * j));
		}
	}
	return dp[n];

}

2.本题小节

        思考:首先要明确递推公式的由来,本题的核心就是将一个数字拆成两个数字,然后进行乘积,被拆得数字还可以继续拆,直到不能拆为止,观察递推公式可以看出,在拆分得过程中供dp[i]选择得情况有三种:选择dp[i],证明这次拆分的两种结果都不及dp[i]大,这种情况一般出现在拆分的后半段,dp[i]已经获得最大值时;选择dp[i - j] * j,说明i被拆成了三个即三个以上的数, 如10被拆成了3,3,4,这情况就是dp[7] * 3,dp[7] 最大值是被拆成3 * 4 时;选择(i - j)* j时,如dp[4],为2 * 2。当然这几种情况都是举例子,实际上也会出现dp[i - j] * j = (i - j) * j的情况。由于i需要拆分为正整数,因此初始化时i = 0 和 i = 1的情况是不存在的,没有意义。

        基本思路:把握好递归公式的由来和遍历顺序本题就比较好做了,跟着五部曲来。

96.不同的二叉搜索数

 题目链接/文章讲解/视频讲解:代码随想录

1.代码展现

//96 不同的二叉搜索树
int numTrees(int n) {
	//step1 构建dp数组
	//dp[i]的意义是i个节点组成的二叉树的个数
	vector<int> dp(n + 3, 0);
	//step2 推导递推公式
	//dp[i] += dp[j] * dp[i - j - 1]
	//step3 初始化dp数组
	dp[0] = 1;
	dp[1] = 1;
	dp[2] = 2;
	if (n <= 2) {
		return dp[n];
	}
	//step4 开始遍历
	for (int i = 3; i <= n; i++) {
		for (int j = 0; j < i; j++) {
			dp[i] += dp[j] * dp[i - j - 1];
			//step5 打印数组
		}
	}
	return dp[n];

 2.本题小节

        思考:本题的递推公式比较难想到,这个递推公式还是要多多理解,就拿n = 3 来说,当1为根节点时,左边节点个数为0,右边节点个数为2,此时左边的节点分布和dp[0]一样,右边的节点分布情况和dp[2]一样,因此能够组成的情况为dp[0] * dp[2],当2、3为根节点同理,由此可以推导出递推公式。dp数组初始化时注意指针越界,因此容器最小设置为3。

        基本思路:理解递推公式的推导以及遍历顺序,跟着五步走即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值