力扣343. 整数拆分
题目来源(力扣):
https://leetcode.cn/problems/integer-break/
题目描述:
给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k >= 2 ),并使这些整数的乘积最大化。
返回 你可以获得的最大乘积 。
基本思路:
动态规划经典题目,以n=5为例,
dp[4]=max(1*4,1*dp[4],2*3,2*dp[3],3*2,3*dp[2]);
其中,
1*4, 2*3,//即直接将n拆分为2个整数;
1*dp[4], 2*dp[3], 3*dp[2],//即将n拆分为多个整数;
选择其中最大的即可.
递推公式:
dp[i]=max(1*(n-1),1*dp[n-1],2*(n-2),2*dp[n-2],...,(n-2)*2,(n-2)*dp[2]);
代码实现:
class Solution {
public:
int integerBreak(int n) {
// 1.确定dp数组及其含义
// dp[i] 表示对于数i,可以获得的最大乘积是dp[i]
vector<int> dp(n + 1);
// 2.确定递推方程
// dp[i]=max(1*(n-1),1*dp[n-1],2*(n-2),2*dp[n-2],...,(n-2)*2,(n-2)*dp[2]);
// 3.初始化 n>=2
// dp[0]=0; //0=0+0,由于0不是正整数,所以dp[0]拆分失败
// dp[1]=0; //1=0+1,由于0不是正整数,所以dp[1]拆分失败
dp[2] = 1; // 2=1+1,所以dp[2]=1*1=1
// 4.确定遍历顺序
// i应该从小到大
for (int i = 3; i <= n; i++) {
for (int j = 1; i - j >= 2; j++) {
dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]));
}
}
// 5.打印(部分)数组以判断是否符合预期
// for(int i=2;i<=n;i++)
// cout<<dp[i]<<" ";
// cout<<endl;
return dp[n];
}
};
时间复杂度
O(n*n)
浙公网安备 33010602011771号