随想录Day41 | 343. 整数拆分、96. 不同的二叉搜索树 | 动态规划

85 阅读1分钟

343. 整数拆分

题目链接:343. 整数拆分

思路: 动规五部曲 

1.确定dp数组以及下标的含义

dp[i] 表示将正整数 ii 拆分成至少两个正整数的和之后,这些正整数的最大乘积

2.确定递推公式

当 i ≥ 2 时,假设对正整数 i 拆分出的第一个正整数是 j(1 ≤ j < i),则有以下两种方案:
将 i 拆分成 j 和 i-j 的和,且 i-j 不再拆分成多个正整数,此时的乘积是 j × (i − j);
将 i 拆分成 j 和 i-j 的和,且 i-j 继续拆分成多个正整数,此时的乘积是 j × dp[i − j]。

3.dp数组如何初始化

0 和 1 都不能拆分, dp[2] = 1;

4.确定遍历顺序

从前向后遍历

5.举例推导dp数组

class Solution {
    public int integerBreak(int n) {
        int[] dp = new int[n + 1];
        dp[2] = 1;
        for (int i = 3; i <= n; i++) {
            for (int j = 1; j <= i - j; j++) {
                dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j]));
            }
        }
        return dp[n];
    }
}

96. 不同的二叉搜索树

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

思路: 1.确定dp数组以及下标的含义

dp[i]的定义为:从 1 为根节点,到从 i 到根节点,一共可以组成的二叉搜索树的个数。

2.确定递推公式

dp[i] += dp[以j为根节点的左子树个数] * dp[以j为根节点的右子树个数] (1 <= j <= i)
dp[i] = dp[j - 1] * dp[i - j] (1 <= j <= i)

3.dp数组如何初始化

dp[0] = 1, dp[1] = 1。

4.确定遍历顺序

遍历i里面每一个数作为头结点的状态,用j来遍历。

5.举例推导dp数组

class Solution {
    public int numTrees(int n) {
        int[] dp = new int[n + 1];
        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];
    }
}