目录
问题描述:
给定一个正整数 n
,将其拆分为 k
个 正整数 的和( k >= 2
),并使这些整数的乘积最大化。
返回 你可以获得的最大乘积 。
示例 1:
输入: n = 2 输出: 1 解释: 2 = 1 + 1, 1 × 1 = 1。
示例 2:
输入: n = 10 输出: 36 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
实现代码与解析:
动态规划:
class Solution {
public:
//动态规划
int integerBreak(int n)
{
vector<int> dp(n + 1);
dp[2] = 1;//1*1
for(int i = 3; i <= n; i++)
{
int tempMax=0;//更新最大值
for(int j = 1; j < i; j++)
{
tempMax=max(j * (i - j), j * dp[i - j]);
if(dp[i] < tempMax) dp[i] = tempMax;
}
}
return dp[n];
}
};
原理思路:
动态规划来解,首先要明白dp数组的含义,就是 i 的拆分最大乘积,对于dp的初始化,显然最开始能只能推出 2 拆分的最大乘积为 1,dp[0],dp[1]为默认0就行,然后就是确定递推公式,我们将 i 拆分成两个或多个数,获取其中的最大值即可,所以我们需要两层循环来遍历和拆分。
优化版:
class Solution {
public:
//动态规划
int integerBreak(int n)
{
vector<int> dp(n + 1);
dp[2] = 1;//1*1
for(int i = 3; i <= n; i++)
{
for(int j = 1; j <= i / 2; j++)
{
dp[i]=max(max(j * (i - j), j * dp[i - j]),dp[i]);
}
}
return dp[n];
}
};
原理思路:
就改了两个地方,第一处就是把记录最大值的变量取消了,直接dp[ i ]原值比较取一下最大而已,然后就是限制 j 不超过 i 的一半,因为最大的乘积其拆分的结果一定是相似等分的,若 j - i 小于 i 的一半的时候,再对 j - i 拆分显然是不可能在出现拆出相似的结果了。
数学方法:
class Solution {
public:
int integerBreak(int n) {
if (n == 2) return 1;
if (n == 3) return 2;
if (n == 4) return 4;
int result = 1;
while (n > 4) {
result *= 3;
n -= 3;
}
result *= n;
return result;
}
};
原理思路:
将 n 拆分成 m 个 3 最后剩下 4 内的数直接乘,这个证明大家可以自己网上查一下。