力扣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)

posted @ 2024-12-04 10:53  HB_Computer  阅读(41)  评论(0)    收藏  举报