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).
Java Solution 1 – Dynamic Programming
Let dp[i] to be the max production value for breaking the number i. Since dp[i+j] can be i*j, dp[i+j] = max(max(dp[i], i) * max(dp[j], j)), dp[i+j]).
public int integerBreak(int n) { int[] dp = new int[n+1]; for(int i=1; i<n; i++){ for(int j=1; j<i+1; j++){ if(i+j<=n){ dp[i+j]=Math.max(Math.max(dp[i],i)*Math.max(dp[j],j), dp[i+j]); } } } return dp[n]; } |
Java Solution 2 – Using Regularities
If we see the breaking result for some numbers, we can see repeated pattern like the following:
2 -> 1*1 3 -> 1*2 4 -> 2*2 5 -> 3*2 6 -> 3*3 7 -> 3*4 8 -> 3*3*2 9 -> 3*3*3 10 -> 3*3*4 11 -> 3*3*3*2
We only need to find how many 3’s we can get when n> 4. If n%3==1, we do not want 1 to be one of the broken numbers, we want 4.
public int integerBreak(int n) { if(n==2) return 1; if(n==3) return 2; if(n==4) return 4; int result=1; if(n%3==0){ int m = n/3; result = (int) Math.pow(3, m); }else if(n%3==2){ int m=n/3; result = (int) Math.pow(3, m) * 2; }else if(n%3==1){ int m=(n-4)/3; result = (int) Math.pow(3, m) *4; } return result; } |
Hello.
Nice little solution. I come up with a purely mathematical solution (that roughly works due to the fact that the floor function doesn’t have a regular derivative). I’ve just solve an optimization problem with a langragian.
Also the dynamic programming solution is great yet not accurate.
you should have written:
dp[i+j]=Math.max(Math.max(dp[i]*dp[j],i * j), dp[i+j])
otherwise you can have cross product (example: dp[i]*i that doesn’t necessarily sum to i+j).
Also you need to go up to n+1. So the condition is (i + j < n+1)
I obtained the following solution using DP, observing the regularity pattern:
For numbers > 4, we can get answer ie. integerBreak(n) as follows:
if integerBreak(n-1) is odd , then answer is – Adding a 2 to the regularity of the second previous number and multiplying it – ie. integerBreak(n-2)*2
if integerBreak(n-1) is even, then answer is – removing a 2 and adding a 3 to the regularity of the previous number and multiplying it. ie.(integerBreak(n-1)/2)*3
public class Solution {
public int integerBreak(int n) {
int[] dp = new int[Math.max(n+1,5)];
dp[0]=0;
dp[1]=1;
dp[2]=1;
dp[3]=2;
dp[4]=4;
for(int i=5;i<=n;i++)
{
if(dp[i-1] % 2 ==1)
dp[i]=dp[i-2]*2;
else dp[i] = (dp[i-1]/2) * 3;
}
return dp[n];
}
}
how can we prove that the regularities are true?