Day41
343. 整数拆分
题目链接:343. 整数拆分
dp[i]
为 i
拆得到的最大乘积
递推公式:
- 拆成两个数:
j
和i-j
- 拆成多个数:
j
和dp[i-j]
,(dp[i-j]
是使用上一步的拆分,因此是拆成至少两个数)
为什么只拆分i-j
,而不拆分j
:因为递推公式是从头开始递归的,拆分i-j
的时候,已经包含了拆分j
,(递推公式都是从最小可拆分开始的)
初始化:dp {0, 0, 1, ...}
class Solution {
public:
int integerBreak(int n) {
vector<int> dp{0, 1, 1};
dp.resize(n + 1);
for (int i = 3; i < n + 1; ++i) {
for (int j = 1; j <= i / 2/*剪枝*/; ++j) {
dp[i] = max({dp[i], j * (i - j), j * dp[i - j]});
}
}
return dp.back();
}
};
j <= i / 2
这一步骤的剪枝是因为拆分出的乘积最大值,一定是在拆分出的数相等左右得到的,比如拆分
100
100
100,一定是在
5
0
2
50^2
502,
3
3
2
×
34
33^2\times34
332×34,
2
5
4
25^4
254等得到的,而不是
1
×
99
1\times 99
1×99,
2
×
98
2\times 98
2×98等
递推公式中还要和dp[i]
比较是当j
遍历时,固定得到的最大dp[i]
。
96.不同的二叉搜索树
题目链接:96.不同的二叉搜索树
根据根节点的不同,来进一步的细分树结构。
例如
n
=
3
n = 3
n=3
根节点为1,左子树为0个节点,右子树为2个节点
根节点为2,左子树为1个节点,右子树为1个节点
根节点为3,左子树为2个节点,右子树为0个节点
dp[3] = dp[0] * dp[2] + dp[1] * dp[1] + dp[2] * dp[0]
递推公式:dp[i] = dp[0] * dp[i - 1] + dp[1] * dp[i - 2] + ... + dp[i - 1] * dp[0]
初始化:dp[0] = 1
遍历顺序:从小到大
class Solution {
public:
int numTrees(int n) {
vector<int> dp{1};
dp.resize(n + 1);
for (int i = 1; i < n + 1; ++i) {
//求和的递推公式
for (int j = 1; j < i + 1; ++j) {
dp[i] += dp[j - 1] * dp[i - j];
}
}
return dp.back();
}
};