LC.343. 整数拆分(DP&数学)
思路:
一. 。令 表示 能分成若干个正整数的最大乘积。
对于第1个数我们可以分成 。
显然若第二个数还可以分答案为: ,否则为: 。
所以状态转移为:
class Solution {
public:
int integerBreak(int n) {
vector<int>dp(n+1,0);
for(int i=2;i<=n;i++){
int mx=0;
for(int j=1;j<i;j++)
mx=max(mx,max(i-j,dp[i-j])*j);
dp[i]=mx;
}
return dp[n];
}
};
二.数学做法.
最后答案可能的情况。
1.答案不可能含有 的数,因为当 时, 显然可以分成两个乘积比和大的数,比如 ,对于 ,也可以用 代替,即答案不含有 的数。
2.当 时,答案不含1,因为这个 显然可以加到其他数上使答案更大。
3. 时, 的个数小于 个,因为 个2可以换成 个3。
4. 时,显然答案为 。
扫描二维码关注公众号,回复:
11487922 查看本文章
因此我们只需特判 的个数是多少个,剩下的都是3即可。
当 显然全为3.
当 ,显然只有一个2.
当 ,显然要拿出一个 ,凑成两个2.
class Solution {
public:
int integerBreak(int n) {
if(n<4) return n-1;
int x=n/3,y=n%3;
if(!y) return pow(3,x);
else if(y==2) return pow(3,x)*2;
else return pow(3,x-1)*4;
}
};
三.由数学做法,我们显然可以优化 过程,特判 ,将 改为 即可。
class Solution {
public:
int integerBreak(int n) {
if(n<4) return n-1;
vector<int>dp(n+1,0);dp[2]=1;
for(int i=3;i<=n;i++)
dp[i]=max({2*(i-2),2*dp[i-2],3*(i-3),3*dp[i-3]});
return dp[n];
}
};