343. 整数拆分
给定一个正整数
n
,将其拆分为k
个 正整数 的和(k >= 2
),并使这些整数的乘积最大化。返回 你可以获得的最大乘积 。
示例 1:
输入: n = 2 输出: 1 解释: 2 = 1 + 1, 1 × 1 = 1。示例 2:
输入: n = 10 输出: 36 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
这种题目,我们第一眼肯定都是直接原地暴力破解,直接利用回溯去试一下
class Solution {int max;int sum = 1;public int integerBreak(int n) {if(n == 2) return 1;if(n == 3) return 2;max = Integer.MIN_VALUE;dfs(n);return max;}void dfs(int n){if(n<0) return;if(n == 0){max=Math.max(max,sum);return;}for(int i =1;i<= n && n>0;i++){sum = sum*i;dfs(n-i);sum = sum/i;}}
}
结果很遗憾,经典时间超限。所以我们可以来进行优化一下。
可以通过记录我们已经运行过了乘积,免去多余的运行(可以说是剪枝)
class Solution {public int integerBreak(int n) {if (n == 2) return 1; if (n == 3) return 2; //这里是两种的特殊情况return dfs(n, new int[n + 1]);}private int dfs(int n, int[] memo) { //这里的memo数组就是用来记录运行过的if (n == 2) return 2;if (memo[n] > 0) return memo[n]; //如果大于0,就是已经被记录了,直接返回就行int max = 0;for (int i = 1; i < n; i++) {max = Math.max(max, i * Math.max(n - i, dfs(n - i, memo)));}memo[n] = max;return max;}
}
一运行,我们就发现我们过了。然后,我们还可以通过递推优化,就是动态规划。
我们先要确定:dp[i] 是什么,其实是n == i时候的拆分出来的整数的最大乘积。
提出一个问题,这个怎么求出来呢?
我们其实可以有两种方式获得dp[i]
第一种:i*(n-i) 这是两个数直接求
第二种:i*(dp[n-i]) 这里是和多个数求
class Solution {public int integerBreak(int n) {int[] dp = new int[n+1];dp[0] = dp[1] = 0;for(int i =2;i<=n;i++){int temp = 0;for(int j = 1;j<= i;j++){temp = Math.max(Math.max(j*(i-j),j*dp[i-j]),temp);//这里是比较两种求值的所有情况,最后获得最大值}dp[i] = temp;}return dp[n];}
}