LeetCode 343 整数拆分
题目链接:https://leetcode.cn/problems/integer-break/
思路:
把一个数拆分成近似的m个数所得的乘积有可能最大
动规五部曲:
dp[i]代表的是第i个数的最大乘积
递归公式:
可以想 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],要取最大值
初始化
显然,0和1不可以拆分,所以dp[0]和dp[1]都为0,dp[2]=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];
}
};
总结
想不到递归公式啊
今日总结:
有点类似数学的找规律题了,当初这方面就很差,只能死记硬背了。