343. 整数拆分
给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k >= 2 ),并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。
示例 1: 输入: n = 2 输出: 1 解释: 2 = 1 + 1, 1 × 1 = 1。 示例 2: 输入: n = 10 输出: 36 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
提示:
- 2 <= n <= 58
思路
第一步:确定dp数组和下标的含义
定义一个一维数组 dp,其中 dp[i] 表示整数 i 被拆分为至少两个正整数的和之后,这些正整数的最大乘积。
第二步:确定递推公式
为了求出 dp[i],我们可以考虑拆分 i 的所有可能性,然后找出最大乘积。具体来说,i 可以拆分为 j 和 i-j(其中 1 <= j < i),这时候,乘积的最大值有两种可能:
- j * (i - j)
- j * dp[i - j]
因此,递推公式为: dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]))
第三步:dp数组如何初始化
由于 n 必须被拆分为至少两个正整数的和,所以 dp[1] 和 dp[2] 都应该初始化为 1。
第四步:确定遍历顺序
dp[i] 是基于小于 i 的 dp[j] 值计算的,因此数组 dp 应该从前往后遍历。
第五步:举例推导dp数组
假设 n = 10,那么 dp 数组初始化为:
- dp[1] = 1
- dp[2] = 1
然后,通过递推公式,我们可以得到:
- dp[3] = max(1 * 2, 1 * dp[2]) = 2
- dp[4] = max(2 * 2, 2 * dp[2]) = 4
- dp[5] = max(3 * 2, 3 * dp[2]) = 6
- dp[6] = max(3 * 3, 3 * dp[3]) = 9
- dp[7] = max(4 * 3, 4 * dp[3]) = 12
- dp[8] = max(4 * 4, 4 * dp[4]) = 16
- dp[9] = max(5 * 4, 5 * dp[4]) = 20
- dp[10] = max(6 * 4, 6 * dp[4]) = 36
最终结果是 dp[10] = 36。
题解
class Solution {
public:
int integerBreak(int n) {
vector<int> dp(n + 1, 1);
for (int i = 3; i <= n; ++i) {
for (int j = 1; j < i; ++j) {
dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]));
}
}
return dp[n];
}
};
96. 不同的二叉搜索树
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
示例 1:
输入:n = 3 输出:5 示例 2: 输入:n = 1 输出:1 提示:
- 1 <= n <= 19
思路
第一步:确定dp数组和下标的含义
定义一个一维数组dp,其中dp[i]表示有i个节点的二叉搜索树(BST)的数量。
第二步:确定递推公式
当有i个节点时,我们可以选择任何一个节点作为根节点。假设选择了数字j作为根节点,那么1, 2, ..., j-1这j-1个节点只能出现在左子树中,j+1, j+2, ..., i这i-j个节点只能出现在右子树中。
因此,以j为根节点的BST的数量是dp[j-1] * dp[i-j]。
递推公式为:
第三步:dp数组如何初始化
只有一个节点或没有节点的BST只有一种可能,所以dp[0] = 1和dp[1] = 1。
第四步:确定遍历顺序
我们需要从小到大计算dp[i],因为dp[i]是基于小于i的dp[j]值计算的。
第五步:举例推导dp数组
假设n = 3,则dp数组初始为:
- dp[0] = 1
- dp[1] = 1
然后,通过递推公式,我们可以得到:
- dp[2] = dp[0]*dp[1] + dp[1]*dp[0] = 2
- dp[3] = dp[0]*dp[2] + dp[1]*dp[1] + dp[2]*dp[0] = 5
最终结果是dp[3] = 5。
题解
class Solution {
public:
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 = 1; j <= i; ++j) {
dp[i] += dp[j - 1] * dp[i - j];
}
}
return dp[n];
}
};