美文网首页剑指offer的java实现-数据结构与算法
剑指offer第二版-14.剪绳子(动态规划)

剑指offer第二版-14.剪绳子(动态规划)

作者: ryderchan | 来源:发表于2017-07-06 10:14 被阅读387次

本系列导航:剑指offer(第二版)java实现导航帖

面试题14:剪绳子

题目要求:
给你一根长度为n的绳子,请把绳子剪成m段,记每段绳子长度为k[0],k[1]...k[m-1],求k[0]k[1]...k[m-1]的最大值。已知绳子长度n为整数,m>1(至少要剪一刀,不能不剪),k[0],k[1]...k[m-1]均要求为整数。
例如,绳子长度为8时,把它剪成3-3-2,得到最大乘积18;绳子长度为3时,把它剪成2-1,得到最大乘积2。

解题思路:
本题有动态规划算法的几个明显特征:
(1)是求最优解问题,如最大值,最小值;
(2)该问题能够分解成若干个子问题,并且子问题之间有重叠的更小子问题。
通常按照如下4个步骤来设计一个动态规划算法:
(1)刻画一个最优解的结构特征;
(2)递归地定义最优解的值;
(3)计算最优解的值,通常采用自底向上的方法;
(4)利用计算出的信息构造一个最优解。
以此题为例,我们定义长度为n的绳子剪切后的最大乘积为f(n),剪了一刀后,f(n)=max(f(i)*f(n-i));假设n为10,第一刀之后分为了4-6,而6也可能再分成2-4(6的最大是3-3,但过程中还是要比较2-4这种情况的),而上一步4-6中也需要求长度为4的问题的最大值,可见,各个子问题之间是有重叠的,所以可以先计算小问题,存储下每个小问题的结果,逐步往上,求得大问题的最优解。

package chapter2;
/**
 * Created by ryder on 2017/7/5.
 * 剪绳子
 */
public class P96_CuttingRope {
    public static int maxCutting(int length){
        if(length<2) return 0;
        if(length==2)return 1;
        if(length==3)return 2;
        int[] dp = new int[length+1];
        dp[0]=0;
        dp[1]=1;
        dp[2]=2;
        dp[3]=3;
        int max = 0;
        int temp = 0;
        for(int i=4;i<=length;i++){
            max = 0;
            for(int j=1;j<=i/2;j++){
                temp = dp[j]*dp[i-j];
                if(temp>max)
                    max = temp;
            }
            dp[i] = max;
        }
        return dp[length];
    }
    public static void main(String[] args){
        for(int i=2;i<10;i++){
            System.out.println("长度为"+i+"的最大值->"+maxCutting(i));
        }
    }
}

运行结果

长度为2的最大值->1
长度为3的最大值->2
长度为4的最大值->4
长度为5的最大值->6
长度为6的最大值->9
长度为7的最大值->12
长度为8的最大值->18
长度为9的最大值->27

上述算法的时间复杂度为o(n^2);但其实,可以使用贪婪算法在o(1)时间内得到答案:n<5时,和动态规划一样特殊处理;n>=5时,尽可能多地剪长度为3的绳子,当剩下的绳子长度为4时,剪成2-2;比如长度为13的绳子, 剪成3-3-3-2-2;贪婪算法虽然快,但一般都思路奇特,可遇不可求。且面试官一般都会要求证明,数学功底要好 。

相关文章

网友评论

  • 我要牛肉面面:自己写了一个简短的证明:https://www.jianshu.com/p/0a13e48aa4af
    写完以后发现大致的思想也是动态规划
  • 蛋黄也可以很有派:我懂了,因为for循环里j从1开始已经是满足了至少剪一刀的条件,细分下来的子问题的大难应该是可以一刀都不剪的。比如4,分为1,3和2,2 那么f(3)可以剪0刀,就是自己,如果f(3)=2的话,就等于规定说3这部分必须还要剪,实际上可以不剪
  • 蛋黄也可以很有派:为什么dp[3]=3,长度为3的绳子,最少剪一刀,难道乘积最大不是 剪成1,2两端,1*2=2吗 ,请问?
    yia宁:最前面特别判断了0-3的情况。
  • 灵璇:第一个动态规划的product数组是不是有点问题,product的那几个初始值和一开始那几个if判断的返回值不同,感觉product的那里还包含了没减的情况,如果是包含的了这样的情况,问什么max不直接初始化为当前假设的那个子问题的长度i呢?
    ryderchan:(1)初始值与几个if判断之所以不同,是因为题目中要求至少剪一刀。可以先忽略这句话,把下面的问题想清楚再来看这句。
    (2)你可以先考虑这个问题:如果可以一刀都不剪,那么这道题要怎么做。把这个问题做出来再考虑加入“至少剪一刀”这个条件后的解题方法。
    (3)如果想不清楚括号2的问题,再简单些,可以列举下长度从1到10的绳子,在可以一刀都不剪以及至少剪一刀这两个问题的结果分别是多少。
    如果(3)(2)(1)还是不清楚,或者搞清楚了(1)(2)(3),对我的代码还有不解,可以继续留言。
    动态规划的确包含了由小到大的问题的结果,但有些题目会有特殊性,特殊值,就比如这道题。

本文标题:剑指offer第二版-14.剪绳子(动态规划)

本文链接:https://www.haomeiwen.com/subject/ulzchxtx.html