【代码训练营】day40 | 343. 整数拆分 & 96.不同的二叉搜索树

所用代码 java

整数拆分 LeetCode 343

题目链接:整数拆分 LeetCode 343 - 中等

思路

无。


尽可能拆成m个近似相同的数,乘积才是最大。

  • dp数组含义:整数i拆分之后最大的乘积为dp[i]
  • 递推公式: 2个数:j x (i - j) => 3个及以上:j x dp[i-j]
  • 初始化:dp[0] = 0, dp[1] = 0, dp[2] = 1
  • 遍历方向:左到右 3<=n 1
  • 打印
class Solution {
    public int integerBreak(int n) {
        int[] dp = new int[n+1];
        dp[0] = 0;
        dp[1] = 0;
        dp[2] = 1;
        // dp数组从i=3开始
        for (int i = 3; i <= n; i++) {
            // 数为n可以拆分的情况
            for (int j = 1; j < i; j++) {
                // 比较拆分成两个数大,还是拆分成3及以上的数大,或是拆分之后有没有原来的数大
                dp[i] = Math.max(dp[i], Math.max(j*(i-j), j*dp[i-j]));
            }
        }
        return dp[n];
    }
}

总结

本题的难点在于dp[i] = Math.max(dp[i], Math.max(j*(i-j), j*dp[i-j]));我们在拆分数字的时候,只需要固定一个数j,然后对另一个数进行拆分,然后每次把乘积最大值进行返回,再把固定的数j乘进去就是最大值了。但是我们拆分的情况有i-j种,所以每次得到的最优结果还要保存比较下一次的值,取最优的结果。

此外本题还可以进行优化,对于拆分的次数,只需要令 j <= i/2 就行了,因为对于某个人拆分一半之后,后面的都是一样的数。

另外本题还可以使用贪心思路(有数学证明):我们把n拆分成m个3的乘积是最大的

不同的二叉搜索树 LeetCode 97

题目链接:不同的二叉搜索树 LeetCode 97 - 中等

思路

无。


n=3时,有头结点为1、头结点为2、头结点为3三种情况:

头结点为1 = 左子树0个节点 x 右子树2个节点

头2 = 左 1 x 右 1

头3 = 左2 x 右 1

  • dp数组含义:值为i的不同二叉搜索树有dp[i]种
  • 递推公式:以j为头结点,左子树一定比j小,那么有j-1个结点,右子树一定比j大,有i-j个结点,且左右子树相乘关系, 再把所有以j为头结点的数量加起来,所以: dp[i] += dp[j-1] x dp[i-j]
  • dp数组初始化:dp[0] = 1, dp[1] =1
  • 遍历顺序:小到大 1
  • 打印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++) {
            // 从根结点1到i一个一个的遍历
            for (int j = 1; j <= i; j++) {
                // 每个结点的数量都要加上 左子树数量乘右子树数量
                dp[i] += dp[j-1] * dp[i-j];
            }
        }
        return dp[n];
    }
}

总结

本题主要是要想到我们的根结点的值可以是 1-i 的每一个值,我们需要上这些以j为根结点的数量,其次以j为根结点的数量是左子树的所有情况 右子树的所有情况。

你可能感兴趣的:(代码训练营,算法,leetcode,数据结构,动态规划,java)