【剑指 Offer 14- I. 剪绳子 中等】【343. 整数拆分 中等】【剑指 Offer 14- II. 剪绳子 II 中等】

【剑指 Offer 14- I. 剪绳子 中等】【343. 整数拆分 中等】

给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m-1] 。请问 k[0]*k[1]*...*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

示例 1:

输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
示例 2:

输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36

 

 

给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。

示例 1:

输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1。
示例 2:

输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
说明: 你可以假设 n 不小于 2 且不大于 58。

 

 

2. 使用动态规划

dp[i]:长度为i的绳子切为m段得到的最大乘积

先切一刀,这一刀切下的长度从2到 i- 1,如果后面的不切了,乘积为j*(i - j),如果后面的继续切,那么乘积为j*dp[i - j].

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

 

时间复杂度更低的基于数学推导或者贪心算法推导的解法可参照LeetCode大佬的题解:https://leetcode-cn.com/problems/jian-sheng-zi-lcof/solution/mian-shi-ti-14-i-jian-sheng-zi-tan-xin-si-xiang-by/

结论是:当平均分段,且每段长为3时乘积最大。

因此设:b = n % 3,b为0,1,2。b为0和2的时候没什么可说的,当b为1时:2*2 > 3*1,因此应当拆分出一个3,和1组成4。

class Solution {
public:
    int integerBreak(int n) {
        if(n <= 3)
            return n - 1;
        int res = 0;
        int a = n / 3;
        int b = n % 3;
        if(b == 0)
            res = pow(3, a);
        else if(b == 1)
            res = pow(3, a - 1) * 4;
        else
            res = pow(3, a) * 2;
        return res;
    }
};

 

 

【剑指 Offer 14- II. 剪绳子 II 中等】

在上题的基础上,扩大了求取范围导致要对结果求模,否则会越界。这里用到了循环求模的方法,基于公式:( x * y ) % a = (x%a * y%a) % a,因此:(xn)%a = (xn-1%a * x)%a 

class Solution {
public:
    long powMode(long x, long a, long k) {
        long res = 1;
        for(int i = 0 ; i < a; i++) {
            res = (res % k * x) % k;
        }
        return res;
    }
    int cuttingRope(int n) {
        if(n <= 3)
            return n - 1;
        modeBase = 1000000007;
        int a = n / 3, b = n % 3;
        long res = powMode(3, a - 1, modeBase);
        if(b == 0)
            res = (res * 3) % modeBase;
        else if(b == 2)
            res = (res * 6) % modeBase;
        else
            res = (res * 4) % modeBase;
        return res;
    }
private:
    int modeBase;
};

 

posted @ 2021-03-28 12:19  蓦然闻声  阅读(33)  评论(0编辑  收藏  举报