代码随想录Day41

80 阅读1分钟

343. 整数拆分

力扣题目链接

一切尽在注释中~

class Solution {
public:
    // 动态规划
    int integerBreak(int n) {
        vector<int> dp(n + 1);
        dp[2] = 1;
        for (int i = 3; i <= n ; i++) {
            // 拆分一个数n 使之乘积最大,那么一定是拆分成m个近似相同的子数相乘才是最大的
            // 可以明确的是m一定大于等于2,既然m大于等于2,也就是 最差也应该是拆成两个相同的 可能是最大值。
            // 那么 j 遍历,只需要遍历到 n/2 就可以,后面就没有必要遍历了,一定不是最大值。
            for (int j = 1; j <= i / 2; j++) {
                // 在每次迭代中,通过比较以下两个值来更新 dp[i] :
                /* 1. (i - j) * j :这表示两个数字 (i-j) 和 j 的乘积,对应于将 i 分解成两个数字。
                2. dp[i - j] * j :这表示将 i-j 分解的最大乘积和 j 的乘积,对应于将 i 分解成多个数字。

                通过取上述两个值的最大值,确定了将 i 分解的最大乘积,并将其存储在 dp[i] 中。这个过程对所有从3到 n 的 i 值重复执行,最终, dp[n] 表示将给定的整数 n 分解的最大乘积。 */
                dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
            }
        }
        return dp[n];
    }
};

96.不同的二叉搜索树

力扣题目链接

class Solution {
public:
    // 时间复杂度:$O(n^2)$
    // 空间复杂度:$O(n)$
    int numTrees(int n) {
        vector<int> dp(n + 1);
        dp[0] = 1;
        for (int i = 1; i <= n; i++) {//这个j表示选择值为j的值作为根节点
            //1...i  一共i个节点组成排序二叉树   dp[i]   最终计算到dp[n]
            //依次计算以某一个值作为根节点,如  j作为根
            //这种情况下,有   dp[j-1]*[i-j]种树;
            //把所有的情况相加  可以得到i个数 组成排序二叉树的种类数量  最终计算到dp[n]
            for (int j = 1; j <= i; j++) {
                dp[i] += dp[j - 1] * dp[i - j];
            }
        }
        return dp[n];
    }   
};