LeetCode Day43

84 阅读1分钟

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),这时候,乘积的最大值有两种可能:

  1. j * (i - j)
  2. 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-1j-1个节点只能出现在左子树中,j+1, j+2, ..., ii-j个节点只能出现在右子树中。

因此,以j为根节点的BST的数量是dp[j-1] * dp[i-j]

递推公式为:

第三步:dp数组如何初始化

只有一个节点或没有节点的BST只有一种可能,所以dp[0] = 1dp[1] = 1

第四步:确定遍历顺序

我们需要从小到大计算dp[i],因为dp[i]是基于小于idp[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];
    }
};