代码随想录 动态规划||343 96

Day35

343. 整数拆分

力扣题目链接

给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。

思路

  • 动规逻辑

  • 确定dp数组(dp table)以及下标的含义

  • dp[i]指的是拆分数字i能得到的最大成绩dp[i]

  • 确定递推公式

  • 比如要拆分10,就要分析是2×8 3×7...这个可以通过一个循环解决,每次从2开始循环,拆分i,并不断更新dp[i]的最大值

  • dp数组如何初始化

  • dp[2] = 1是确定的,但dp[0]和dp[1]设置初始值为0就行,因为反正也不会从他们这里面选

  • 确定遍历顺序

  • dp[i]是从前面得来的,从前往后遍历

  • 举例推导dp数组

  • 5 -> 2 * 3; 8 -> 3 * (2 * 3); 10 -> 2 *(3* (2*3) )

  • 时间复杂度O(n2),空间复杂度O(n)

  • 贪心逻辑

  • 只要n还大于4,就把n分出来一个3,然后把res再和最后的n相乘

  • 时间复杂度O(n),空间复杂度O(1)

代码

class Solution {
    public int integerBreak(int n) {
        if (n == 1 || n == 2) return 1;
        if (n == 3) return 2;
        int res = 1;
        while (n > 4){
            n -= 3;
            res *= 3;
        }
        res *= n;
        return res;
    }
}

class Solution {
    public int integerBreak(int n) {
        int[] dp = new int[n + 1];
        dp[2] = 1;//初始化
        for (int i = 3; i <= n; i++) {//外层计算dp[i]
            for (int j = 2; j <= i; j++) {//内层计算拆分的情况
                dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j]));//从后面两个中挑选,不断更新dp[i]最大值
            }
        }
        return dp[n];
    }
}

96.不同的二叉搜索树

力扣题目链接

给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?

思路

  • 确定dp数组(dp table)以及下标的含义

  • dp[i]是从1到i这些数字组成不同的二叉搜索树的个数

  • 确定递推公式

  • dp[3] = dp[0] * dp[2] + dp[1] * dp[1] + dp[2] * dp[0]

  • 1~3这三个元素组成的二叉搜索树个数,1为头节点+2为头节点+3为头节点

  • 1为头节点:左子树0个元素的二叉搜索树 * 右子树2个元素的二叉搜索树

  • ...

  • dp数组如何初始化

  • dp[0] = 1, dp[1] = 1

  • 确定遍历顺序

  • 从前往后

  • 举例推导dp数组

代码

class Solution {
    public int numTrees(int n) {
        int[] dp = new int[n + 1];
        dp[0] = 1;
        dp[1] = 1;//初始化dp数组
        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];
    }
}

你可能感兴趣的:(动态规划,算法,leetcode,java)