原题:
Given a positive integer n, break it into the sum of at least two positive integers and maximize the product of those integers. Return the maximum product you can get.
For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 + 4).
Note: you may assume that n is not less than 2.
Hint:
There is a simple O(n) solution to this problem.
You may check the breaking results of n ranging from 7 to 10 to discover the regularities.
第一种思路是动态规划,时间复杂度为O(n^2),动态规划时,只取两个数的和就可以,因为三个数的和(以及三个数以上的和)都是由两个数的和分解来的。
还需要注意的是,有时间分解了还不如不分解,比如2,3,因此,我们使用Math.max(j,dp[j]),当分解了更小时,不分解。
代码如下:
//存在重复计算,所以很容易想到用动态规划
//一开始的dp思想是dp[i] = dp[j]*dp[i-j],但是有时候拆开反而会降低j的值,即存在dp[j]<j的情况
//对于这种情况,我们选择不拆开,即使用Math.max(dp[j], j)
public int integerBreak(int n) {
if(n<=2){return 1;}
int[] dp = new int[n+1];
dp[1] = 1;dp[2] = 1;dp[3] = 2;
for(int i=4;i<=n;i++){
int maxValue = Integer.MIN_VALUE;
for(int j=1;j<i;j++){
int acm = Math.max(dp[j], j)*Math.max(dp[i-j], i-j);
if(acm>maxValue){
maxValue = acm;
}
dp[i] = maxValue;
}
}
return dp[n];
}
//将一个整数分解成至少两个数的和,并且这些数的乘积最大。
//观察,将2,3分解时,还不如不分解。
//将4,5,6分解时可以得到比不分解大的值
//所以我们的规则是:1、一定不含有1,任何一个数加1的值比乘以的1大。
//2、遇到2,3就不分解了。
//3、5以上的一定要分解
//综上所述,所有的数要么分解成2和3的乘积(模3余2时),要么分解成3和4的成绩(模3余1时)。
public int integerBreak(int n) {
if(n<=2){
return 1;
}else if(n==3){
return 2;
}
if(n%3==0){ //分解为全3
return (int)(Math.pow(3,n/3));
}else if(n%3==1){ //分解为很多3和一个4
return (int)(Math.pow(3,(n-4)/3))*4;
}else{
return (int)(Math.pow(3,(n-2)/3))*2;
}
}