剑指 Offer 14- I. 剪绳子


剑指 Offer 14- I. 剪绳子

难度中等 168
给你一根长度为 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.

    public int cuttingRope(int n) {
        int[] dp = new int[n + 1];
        dp[2] = 1;
        for(int i = 3; i < n + 1; i++)&#123;
            for(int j = 2; j < i; j++)&#123;
                System.out.print("dp["+i+"]="+dp[i]+",i="+i+",j="+j+",dp["+(i-j)+"]="+dp[i-j]);
                dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j]));
                System.out.println(",dp["+i+"]="+dp[i]);
            &#125;
        &#125;
        return dp[n];
    &#125;

解析
动态规划

这题用动态规划是比较好理解的:
我们想要求长度为 n 的绳子剪掉后的最大乘积,可以从前面比 n 小的绳子转移而来。
用一个 dp 数组记录从 0 到 n 长度的绳子剪掉后的最大乘积,也就是dp[i]表示长度为 i 的绳子剪成 m 段后的最大乘积,初始化 dp[2] = 1。
我们先把绳子剪掉第一段(长度为 j),如果只剪掉长度为 1,对最后的乘积无任何增益,所以从长度为 2 开始剪,
剪了第一段后,剩下(i - j)长度可以剪也可以不剪。如果不剪的话长度乘积即为 j _ (i - j);如果剪的话长度乘积即为 j _ dp[i - j]。取两者最大值 max(j _ (i - j), j _ dp[i - j])。
第一段长度 j 可以取的区间为[2,i),对所有 j 不同的情况取最大值,因此最终 dp[i]的转移方程为:
dp[i] = max(dp[i], max(j _ (i - j), j _ dp[i - j]))。
最后返回 dp[n]即可。

作者:edelweisskoko
链接:https://leetcode-cn.com/problems/jian-sheng-zi-lcof/solution/jian-zhi-offer-14-i-jian-sheng-zi-huan-s-xopj/
image.png


文章作者:   future
版权声明:   本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 future !
 上一篇
92. 反转链表 II--🀄️ 92. 反转链表 II--🀄️
92. 反转链表 II难度中等 690反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。说明:1 ≤ m ≤ n ≤ 链表长度。示例:输入: 1->2->3->4->5->NULL, m = 2, n =
下一篇 
43. 字符串相乘--🀄️ 43. 字符串相乘--🀄️
43. 字符串相乘难度中等 574给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。示例 1:输入: num1 = “2”, num2 = “3”输出: “6”示
  目录