给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。
示例 :
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1。
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
说明: 你可以假设 n 不小于 2 且不大于 58。
思路:dp[i]表示i拆分为至少两个正整数的最大乘积。对所有可能的拆分做遍历:dp[i]=dp[i-j]*j;由于dp[2]=1,dp[3]=2,比金额本身要小(即不拆分值更大),所以,当i>3时,令dp[2]=2,dp[3]=3
int integerBreak(int n) {
if(n<3)return 1;
if(n==3)return 2;
vector<int>dp(n+1);
dp[2]=2;
dp[3]=3;
for(int i=3;i<=n;i++){
for(int j=2;j<i;j++){
dp[i]=max(dp[i],dp[i-j]*j);
}
}
return dp[n];
}
一种数学方法,可以论证只有拆分为2或者3的时候,乘积最大,且优先选择3。感兴趣的可以看一下
I saw many solutions were referring to factors of 2 and 3. But why these two magic numbers? Why other factors do not work?
Let’s study the math behind it.
For convenience, say n is sufficiently large and can be broken into any smaller real positive numbers. We now try to calculate which real number generates the largest product.
Assume we break n into (n / x) x’s, then the product will be xn/x, and we want to maximize it.
Taking its derivative gives us n * xn/x-2 * (1 - ln(x)).
The derivative is positive when 0 < x < e, and equal to 0 when x = e, then becomes negative when x > e,
which indicates that the product increases as x increases, then reaches its maximum when x = e, then starts dropping.
This reveals the fact that if n is sufficiently large and we are allowed to break n into real numbers,
the best idea is to break it into nearly all e’s.
On the other hand, if n is sufficiently large and we can only break n into integers, we should choose integers that are closer to e.
The only potential candidates are 2 and 3 since 2 < e < 3, but we will generally prefer 3 to 2. Why?
Of course, one can prove it based on the formula above, but there is a more natural way shown as follows.
6 = 2 + 2 + 2 = 3 + 3. But 2 * 2 * 2 < 3 * 3.
Therefore, if there are three 2’s in the decomposition, we can replace them by two 3’s to gain a larger product.
All the analysis above assumes n is significantly large. When n is small (say n <= 10), it may contain flaws.
For instance, when n = 4, we have 2 * 2 > 3 * 1.
To fix it, we keep breaking n into 3’s until n gets smaller than 10, then solve the problem by brute-force.
//由数学方法写出的代码
int integerBreak(int n) {
if(n<3)return 1;
if(n==3)return 2;
int res=1;
while(n>4){
res*=3;
n-=3;
}
return res*n;
}