(40/60)整数拆分、不同的二叉搜索树
渐入佳境
整数拆分
leetcode:343. 整数拆分
动态规划
思路
-
意义:i拆分乘积的最大值为
dp[i] -
递推:
dp[i] = max{dp[i],j*(i-j),j*dp[i-j]} -
初始化:从2开始可以拆,有意义,
dp[2] = 1,其他为0 -
遍历顺序:
for(int i = 3;i <= n;i++) // 0、1没意义,2已经赋值了,从3开始 for(int j = 1;j <= i/2;j++) // 拆出0没有意义,从1开始。取到i/2就可以,再往后重复。
复杂度分析
时间复杂度:O(N^2)。
空间复杂度:O(N)。
注意点
略
代码实现
class Solution {
public:
/*
i拆分乘积最大为dp[i]
dp[i] = max{dp[i],j*(i-j),j*dp[i-j]}
dp[0] = 0;dp[1] = 0;dp[2] = 1;
i: 3~n j: 1~i/2
*/
int integerBreak(int n) {
vector<int> dp(n + 1,0); // 数组大小比最大下标大1
dp[2] = 1;
for(int i = 3;i <= n;i++){
for(int j = 1;j <= i/2;j++){
dp[i] = max(dp[i],max(j * (i-j),j * dp[i-j]));
}
}
return dp[n];
}
};
TypeScript:
/*
i拆分乘积最大为dp[i]
dp[i] = max{dp[i],j*(i-j),j*dp[i-j]}
dp[0] = 0;dp[1] = 0;dp[2] = 1;
i: 3~n j: 1~i/2
*/
function integerBreak(n: number): number {
let dp:number[] = new Array(n + 1).fill(0);
dp[2] = 1;
for(let i = 3;i <= n;i++){
for(let j = 1;j <=i/2;j++){
dp[i] = Math.max(dp[i],j * (i-j),j * dp[i-j]);
}
}
return dp[n];
};
不同的二叉搜索树
leetcode:96. 不同的二叉搜索树
动态规划
思路
通过画图找到了规律,i个节点就是一个节点的基础上,分配i-1个节点在左右子树的问题
-
意义:i个节点有
dp[i]种不同的二叉搜索树 -
遍历和递推:
dp[i] = dp[j] + dp[i-1-j]for(int i = 2;i <= n;i++){ for(int j = i-1;j >= i/2;j--){ // i-1拆成j和i-1-j if(j == i - 1 - j) // 拆出两个相等数时不乘2(轴对称) dp[i] += dp[j] * dp[i-1-j]; else // 拆出不对称时,有对称的两个解 dp[i] += 2 * dp[j] * dp[i-1-j]; } } -
初始化:
dp[0] = 1;dp[1] = 1;dp[0]没有意义但是需要赋值为1以保持递推公式的一致。
复杂度分析
时间复杂度:O(N^2)。
空间复杂度:O(N)。
注意点
- JS数字除法会变成小数,
代码实现
class Solution {
public:
/*
本质上就是求n个节点的二叉搜索树可能的形状数
*/
int numTrees(int n) {
vector<int> dp(n + 1,0);
dp[0] = 1;dp[1] = 1;
for(int i = 2;i <= n;i++){
for(int j = i-1;j >= i/2;j--){
// i-1拆成j和i-1-j
if(j == i - 1 - j) // 拆出两个相等数时不乘2(轴对称)
dp[i] += dp[j] * dp[i-1-j];
else // 拆出不对称时,有对称的两个解
dp[i] += 2 * dp[j] * dp[i-1-j];
}
}
return dp[n];
}
};
TypeScript:
function numTrees(n: number): number {
let dp:number[] = new Array(n + 1).fill(0);
dp[0] = 1; dp[1] = 1;
for(let i = 2;i <= n;i++){
for(let j = i-1;j >= Math.floor(i/2);j--){
// i-1拆成j和i-1-j
if(j === i-1-j){
dp[i] += dp[j] * dp[i-1-j]; // 拆出两个相等数时不乘2(轴对称)
}
else{ // 拆出不对称时,有对称的两个解
dp[i] += 2 * dp[j] * dp[i-1-j];
}
}
}
return dp[n];
};

浙公网安备 33010602011771号