Day41 动态规划 LeetCode 343 96

101 阅读2分钟

343. 整数拆分

心得

  • 拿到题目瞎想,感觉相等的数值乘积应该最大,其实应该是拆分的时候,尽可能当前个数情况下,每个值相等,当时想的是平方根之后近可能靠近这个值,显然存在问题,本题确实存在数学优化解,而是尽可能拆分3的倍数,余下4或者都是3,不要想当然;应该从迭代角度,看看能够拆分老老实实迭代求加

题解

  • 确定好dp数字含义,固定迭代处,拆分情况分别讨论即可,注意j的情况无需再拆分,在迭代过程中已经包含拆分过程,同时拆分求方案最值,此外优化了拆分的各值相等情况的计算量,在此处才是想的优化点
// 时间O(N^2),空间O(N)
class Solution {
public:
    int integerBreak(int n) {
        vector<int> dp(n + 1); // dp[i] 表示将i拆分得到的最大乘积
        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];
    }
};

// 贪心,时间O(N) 空间(1)
class Solution {
public:
    int integerBreak(int n) {
        if (n == 2) return 1;
        if (n == 3) return 2;
        if (n == 4) return 4;
        int result = 1;
        while (n > 4) {
            result *= 3;
            n -= 3;
        }
        result *= n;
        return result;
    }
};

96. 不同的二叉搜索树

心得

  • 递推公式推错,算的是(n-1) *2 + 1,尤其是代入3的时候,这时候应该考虑1结点的时候能够覆盖,这样递推公式取决前两个状态,毕竟mid题目,只和前一个相关太牵强
  • 最本质的办法还是从根节点入手,自己想的是上一种形态入手每个都可以首位插入,然后外加一种特殊情况,想的复杂了

题解

  • 注意递推公式推理,从根节点入手,跟前两种状态相关,注意迭代顺序
class Solution {
public:
    int numTrees(int n) {
        vector<int> dp(n + 1, 0); // 1. dp[i] n个结点组成的1-n互不相同BST个数
        dp[0] = 1;  // 3. 空节点算一种
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= i; j++) { // 4. 遍历顺序,从小到大,累加
                dp[i] += dp[j - 1] * dp[i - j]; // 2. 以j为根节点的个数,等于左侧j-1个结点,和右侧i - j种之和 
            }
        }
        return dp[n];
    }
};