整数拆分
思路:第一步想的是用递归做,
int digui(int n){
if(n==1)return n;
return max((n/2)*(n-n/2),digui(n/2)*digui(n-n/2));
}
可惜的是题目并没有规定一定要分成两份,因此这个思路是不对的,但已经初窥门径。正确做法还是用dp,dp[i]的含义是对i进行拆分,所能得到的最大乘积。
curMax = max(curMax, max(j * (i - j), j * dp[i - j]));
表示最大值可能更新自一次拆分或多次拆分。
class Solution {
public:
int integerBreak(int n) {
vector <int> dp(n + 1);
for (int i = 2; i <= n; i++) {
int curMax = 0;
for (int j = 1; j < i; j++) {
curMax = max(curMax, max(j * (i - j), j * dp[i - j]));
}
dp[i] = curMax;
}
return dp[n];
}
};
容易看出本题可以采用数学优化,这里引入两个推论,尤其是第二个最为重要:当拆分个数固定时,每个拆分部分大小接近时拆分乘积最大;数字尽可能以3为因子等分时乘积最大。
证明见:https://leetcode.cn/problems/integer-break/solutions/29098/343-zheng-shu-chai-fen-tan-xin-by-jyd
不同的二叉搜索树
题目链接:96. 不同的二叉搜索树 - 力扣(LeetCode)
思路:从样例里可以看出,如果节点数量是确定的,那么他可以构成的二叉搜索树数量也是固定的,那么我们就能据此构建dp数组。
for(int i=2;i<=n;i++){
for(int j=0;j<i;j++){
dp[i]+=dp[j]+dp[i-j-1];
}
}
但是还是有缺陷,因为当2*j==i-1时会导致多算了一种可能。
错错错,这种算法是错误的,正确计算dp[i]应该是dp[j]*dp[i-j-1],而且不需要将2*j==i-1作为特殊情况单独列出。
class Solution {
public:
int numTrees(int n) {
vector<int> dp(n+1);
dp[0]=1;
dp[1]=1;
for(int i=2;i<=n;i++){
for(int j=0;j<i;j++){
dp[i]+=dp[j]*dp[i-j-1];
}
}
return dp[n];
}
};
标签:int,随想录,二叉,搜索,拆分,343,dp,96 From: https://www.cnblogs.com/Liubox/p/18061254