算法修炼Day41|343. 整数拆分 ● 96.不同的二叉搜索树

83 阅读2分钟

LeetCode:343. 整数拆分 - 力扣(LeetCode)

1.思路

理一下思路:可以用边界排除法做,见代码实现,略。利用动规,将数拆分为多个近似相等的数,一层for循环用来遍历前面每一个数拆分所能得到的最大值,再一层for循环用来实现前面每一个数能取得到的最大值,其中dp[i]随着j一直个更新。

2.代码实现
// 常规思路:找边界值√
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;
    }
}
// 动态规划
class Solution {
    public int integerBreak(int n) {
        // 数尽可能的均质
        // 声明dp[i]数组,数值为i可拆分的最大乘积为dp[i]
        int[] dp = new int[n + 1];
        // 初始化dp[]数组
        dp[2] = 1;
        // 递推公式
        for (int i = 3; i <= n; i++) {
            for (int j = 1; j <= i / 2; j++) {
                dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j]));
            }
        }
        return dp[n];
    }
}

3.复杂度分析

时间复杂度:O(n).

空间复杂度:O(n).

LeetCode:96. 不同的二叉搜索树 - 力扣(LeetCode)

1.思路

太深太巧妙了,根本想不出来。用构建二叉搜索树的方式并且利用其特性来做,当前根节点值确定之后其左右子树的个数就是确定的,左子树的构筑方式✖右子树的构筑个数就是以当前值为根节点的二叉树的方式,将所有值均作为根节点遍历加和一遍就是最终的结果值。第一层for循环遍历到每个节点,第二层for循环根据前面节点值推导出当前节点所能构造的最大二叉树的个数。

2.代码实现
class Solution {
    public int numTrees(int n) {
        // 思路:???
        // 声明dp[]数组:数值为n的二叉搜索树的个数为dp[n]种
        int[] dp = new int[n + 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];
    }
}
3.复杂度分析

时间复杂度:O(n^2).

空间复杂度:O(n).