代码随想录算法训练营第四十一天|343.整数拆分、96.不同的二叉搜索树

174 阅读2分钟

343.整数拆分

题目链接:343. 整数拆分

思路:动态规划五步曲

  1. dp[i]代表拆分数字i可以得到的最大乘积
  2. 递推公式:j从1开始遍历,每次取j*(i - 1)和jdp[i - j]中最大的。j(i - 1)为拆分为两个数的情况,j*dp[i - j]为拆分为两个或两个以上的情况
  3. 初始化:从2开始,dp[2] = 1
  4. 遍历顺序:i和j都是从前向后遍历
  5. 举例证明
class Solution {
    public int integerBreak(int n) {
        // dp[i]代表拆分数字i可以得到的最大乘积
        int[] dp = new int[n + 1];
        // 递推公式:j从1开始遍历,每次取j*(i - 1)和j*dp[i - j]中最大的
        // j*(i - 1)为拆分为两个数的情况,j*dp[i - j]为拆分为两个或两个以上的情况
        // 初始化:从2开始,dp[2] = 1
        dp[2] = 1;
        // 遍历顺序:i和j都是从前向后遍历
        for (int i = 3; i < dp.length; i++) {
            for (int j = 1; j < i - 1; j++) {
                // 遇到大的便更新dp[i],
                dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j]));
            }
        }
        return dp[n];
    }
}

96.不同的二叉搜索树

题目连接:96. 不同的二叉搜索树

思路:动态规划五步曲 本题递推公式推导较为复杂,详情移步随想录网站

  1. dp[i] 表示由i个节点可以组成的二叉搜索树种类
  2. 递推公式:dp[i] += dp[以j为头结点左子树节点数量] * dp[以j为头结点右子树节点数量]
  3. 初始化:dp[0] = 1
  4. 遍历顺序是i从1到n,j从1到i。
  5. 举例证明
class Solution {
    public int numTrees(int n) {
        // dp[i] 表示由i个节点可以组成的二叉搜索树种类
        int[] dp = new int[n + 1];
        // 递推公式:dp[i] += dp[以j为头结点左子树节点数量] * dp[以j为头结点右子树节点数量]

        // 初始化:dp[0] = 1
        dp[0] = 1;
        // 遍历顺序
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= i; j++) {
                dp[i] += dp[j - 1] * dp[i - j];
            }
        }
        return dp[n];
    }
}