343. 整数拆分

343. 整数拆分

1.题目描述

给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。
示例 1:
在这里插入图片描述
示例 2:
在这里插入图片描述
说明: 你可以假设 n 不小于 2 且不大于 58。

2.方法1(动态规划)

dp[i]表示将正整数 i 拆分成至少两个正整数的和之后,这些正整数的最大乘积。特别地,0 不是正整数,1 是最小的正整数,0 和 1 都不能拆分,因此 dp[0]=dp[1]=0。
当 i≥2 时,假设对正整数 i 拆分出的第一个正整数是 j(1≤j<i),则有以下两种方案:
将 i 拆分成 j 和 i−j 的和,且 i−j 不再拆分成多个正整数,此时的乘积是 j×(i−j);
将 i 拆分成 j 和 i−j 的和,且 i−j 继续拆分成多个正整数,此时的乘积是 j×dp[i−j]。
因此,当 j 固定时,有dp[i]=max(j×(i−j),j×dp[i−j])。由于 j 的取值范围是 1 到 i−1,需要遍历所有的 j 得到 dp[i] 的最大值,因此可以得到状态转移方程如下:
dp[i] = max{max(j×(i−j),j×dp[i−j])}
最终得到 dp[n] 的值即为将正整数 n 拆分成至少两个正整数的和之后,这些正整数的最大乘积。

3.代码

class Solution {
public:
    int integerBreak(int n) {
        vector<int> dp(n+1);
        for(int i = 2;i <= n;++i){
            for(int j = 1;j < i;++j){
                dp[i] = max(dp[i],max(j*(i-j),j*dp[i-j]));
            }
        }
        return dp[n];
    }
};

4.复杂度分析

时间复杂度:O(n^2)
空间复杂度:O(n)

5.方法2(数学法)

当两个整数尽量平分n的时候,两个整数的乘积才能达到最大,(比如,当n = 10时,分成两份,必定是5, 5。当n = 11时,分成两份,必定是5、6)
推广:
将n 分成cnt份(cnt <= n),必定是(n % cnt) 个 (n / cnt + 1)和 (cnt - n % cnt )个 (n / cnt)乘积最大。(其中n / cnt是表示均分所得,n % cnt是表示均分成cnt份后多出的1个数,再分给其中 n % cnt 个 n / cnt)(比如,n = 10,求分成cnt = 3份的最大乘积。均分所得 num = n / cnt = 3, 多出的1的个数 为 n % cnt = 1, 再将多出的1分配到其中均分所得的元素中,n / cnt + 1)

6.代码

class Solution {
public:
    int integerBreak(int n) {
        int res = 0;
        for(int i = 2;i <= n;++i){
            int numCount = n % i;//多出1的个数
            res = max(res,(int)(pow(n/i,i-numCount)*pow(n/i+1,numCount)));
        }
        return res;
    }
};

7.复杂度分析

时间复杂度:O(n)
空间复杂度:O(1)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值