原题链接:
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.
Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.
Subscribe to see which companies asked this question
思路:
乍一看,很明显的一道动态规划题目,而且很容易想到的是O(n^2)的解法。
解法一:DP O(n^2)解法
int integerBreak(int n) {
vector<int> dp(n + 1, 1);
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= i + 1; ++j)
{
if(i + j <= n)
{
dp[i + j] = max(max(dp[i], i) * max(dp[j], j), dp[i + j]);
}
}
}
return dp[n];
}
n = 2 max = 1(1 + 1)
n = 3 max = 2(1 + 2)
n = 4 max = 4(2 + 2)
n = 5 max = 6(2 + 3)
n = 6 max = 9(3 + 3)
n = 7 max = 12(3 + 2 + 2)
n = 8 max = 16(2 + 2 + 2 + 2)
n = 9 max = 27(3 + 3 + 3)
n = 10 max = 36(2 + 2 + 3 + 3)
大致也发现了一点规律,我们都分解为1 2 3这样的组合。
很简单,如果组合为4,4又可以分解为2 + 2,如果组合为5,5又可以分解为2 + 3。
以此类推~
上面还有一个规律,如果一个数分解后可以写成全是2或全是3,那么全是3的乘积肯定比全是2的大。
比如6 = 2 + 2 + 2 = 3 + 3 肯定是3*3 > 2*2*2。
所以基于上面的思路,可以写出O(n)的代码了:
int integerBreak(int n) {
if(n <= 3) return n - 1;
vector<int> dp(n + 1, 0);
dp[1] = 1;
dp[2] = 2;
dp[3] = 3;
for(int i = 4; i <= n; ++i)
{
dp[i] = max(2 * dp[ i - 2], 3 * dp[i - 3]);
}
return dp[n];
}
下面写点数学公式:
对于n≥4
n = 4 max = 4
n > 4 下面这个等式肯定是正确的。
3 * (n - 3) > n
上面这个式子说明:将n分解为3 和 n - 3,乘积变大了,对不对。
【不要问我为什么分解为3和n-3
上面分解为2的乘积比分解为3乘积小,系不系?
如果能分解为3,何乐不为呢?
大致这么解释吧~】
继续n-3,按照上面这个规律分解下去。
恩,第二种解法出来了~
解法二:递归
int integerBreak(int n) {
int a[5] = {1, 2, 4, 6, 9};
if(n <= 6) return a[n - 2];
else return 3 * integerBreak(n - 3);
}
分为下面几种情况:
n % 3 == 0 就全部分解为3。
n % 3 == 1 肯定有个4,剩下的分解为3。
n % 3 == 2 有个2,剩下的全部分解为3。
所以,代码也可以这么写~
int integerBreak(int n) {
if(n <= 3) return n - 1;
if(n % 3 == 0) return pow(3, n / 3);
if(n % 3 == 1) return 4 * pow(3, (n - 4) / 3);
if(n % 3 == 2) return 2 * pow(3, n / 3);
}