LeetCode 343. Integer Break

Question

Given a positive integer n, break it into the sum of at least two positive integers and maximize the product of those integers. Return the maximum product you can get.

For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 + 4).

Note: You may assume that n is not less than 2 and not larger than 58.

Analysis

    这个题目有两个解法。一种是动态规划,

递推:f[n] = max(f[n], max((n-k) * f[k] , (n-k) * k)) (0 < k <= n - 1)

初始状态为:f[0] = 0, f[1] = 1。

    还有一种是解析地求解,假设给定的整数为n,将其分解为k个整数a1,a2....ak,积为f(n,k)基于以下两条引理:

  1. 对给定整数n,若确定将其分解为k个整数,求分解各个整数的积的最大值,那么最大值出现在k个数最接近n/k的地方。
  2. 对给定正数n,那么f(n,k)随k的变化趋势是先增加后减小。

    对于1,这是因为算术平均数不小于几何平均数,而且仅在所有的数相等的时候,算术平均等于几何平均。而且,当k固定的时候,f(n,k)随a1,a2....ak的差的增大而减小。

    对于2,由引理1可以得出,(f(n,k))^(1/k)≤n/k,即f(n,k)≤(n/k)^k。现在考察函数f(x)=(C/x)^x,其中C为常数,它在x=C/e的时候取得极大值,函数图像如下图所示。


    鉴于在这个题目中n/e不是整数,所以只需要考察n/e附近的几个整数值,取最大的f(n,k)即可。

Solution 动态规划

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

Solution 解析解

class Solution {
public:
    int integerBreak(int n) {
        int rnt = 1;
        int i = max(int(n / 2.718282) - 1, 2);
        for(int ii = 0; ii < 2; ++ii){
            int prod = 1;
            int cur = 0;
            int rest = n;
            for(int j = i; j >= 1; --j){
                cur = rest / j;
                rest -= cur;
                prod *= cur;
            }
            if(prod < rnt)
                break;
            else
                rnt = prod;
            i++;
        }
        return rnt;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值