题目描述:
给定一个正整数 n
,将其拆分为 k
个 正整数 的和( k >= 2
),并使这些整数的乘积最大化。
返回 你可以获得的最大乘积 。
思路:
此题的动态规划思路比较难想,dp数组的含义是拆分i这个数获得的最大乘积。动态规划究其根本就是可以用到曾经算出来的数据递推出新的数据,这里是如何递推的呢?假设n是5,那么当k=2的时候显然有这么几种方法(1,4)(2,3)(3,2)(4,1)二元组的第一个数很明显是1到n-1。那么继续拆分的情况呢?剩下所有的情况概括一下就是:
注意这里的拆分包括了k的任意情况
一、只拆二元组的一个数:拆1,不拆4;拆2,不拆3,拆3,不拆2;拆4,不拆1;
二、两个数都给拆了:拆1、拆4;拆2、拆3;……
三、两个数都不拆:……
很显然我们只需要找到上面三组数中的最大值就可以了。
那么dp的递推式也就确定了:取以上三种情况的最大值就是dp[i]
for(int j=1;j<i;j++){
dp[i]=max(dp[i],max(dp[i-j]*dp[j],max(dp[j]*(i-j),j*(i-j))));
}
很显然dp[1]和dp[2]的值分别是1和2(这里2不拆如果输入n=2作为特殊情况返回1),那么dp[n]很容易就能求出了
代码:
class Solution {
public:
int integerBreak(int n) {
if(n==2)return 1;
int dp[n+1];
for(int i=0;i<n+1;i++)dp[i]=0;
dp[1]=1;dp[2]=2;
for(int i=3;i<n+1;i++){
for(int j=1;j<i;j++){
dp[i]=max(dp[i],max(dp[i-j]*dp[j],max(dp[j]*(i-j),j*(i-j))));
}
}
for(int i=0;i<n+1;i++)cout<<dp[i]<<' ';
return dp[n];
}
};
结果: