给定一个正整数 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];}
}
给定一个整数 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];}
}