Question
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 and not larger than 58.
Analysis
这个题目有两个解法。一种是动态规划,
递推:f[n] = max(f[n], max((n-k) * f[k] , (n-k) * k)) (0 < k <= n - 1)
初始状态为:f[0] = 0, f[1] = 1。
还有一种是解析地求解,假设给定的整数为n,将其分解为k个整数a1,a2....ak,积为f(n,k)基于以下两条引理:
- 对给定整数n,若确定将其分解为k个整数,求分解各个整数的积的最大值,那么最大值出现在k个数最接近n/k的地方。
- 对给定正数n,那么f(n,k)随k的变化趋势是先增加后减小。
对于1,这是因为算术平均数不小于几何平均数,而且仅在所有的数相等的时候,算术平均等于几何平均。而且,当k固定的时候,f(n,k)随a1,a2....ak的差的增大而减小。
对于2,由引理1可以得出,(f(n,k))^(1/k)≤n/k,即f(n,k)≤(n/k)^k。现在考察函数f(x)=(C/x)^x,其中C为常数,它在x=C/e的时候取得极大值,函数图像如下图所示。
Solution 动态规划
class Solution {
public:
int integerBreak(int n) {
vector<int> dp(n + 1);
dp[1] = 1;
for (int i = 2; i <= n; i++) {
for (int j = 1; j < i; j++) {
dp[i] = max(dp[i], max(j, dp[j]) * (i - j));
}
}
return dp[n];
}
};
Solution 解析解
class Solution {
public:
int integerBreak(int n) {
int rnt = 1;
int i = max(int(n / 2.718282) - 1, 2);
for(int ii = 0; ii < 2; ++ii){
int prod = 1;
int cur = 0;
int rest = n;
for(int j = i; j >= 1; --j){
cur = rest / j;
rest -= cur;
prod *= cur;
}
if(prod < rnt)
break;
else
rnt = prod;
i++;
}
return rnt;
}
};