题目的主要信息:把一根长度为nnn的绳子分成mmm段,每段长度都是整数求每段长度乘积的最大值举一反三:学习完本题的思路你可以解决如下题目:JZ83. 剪绳子(进阶版)JZ71. 跳台阶扩展问题JZ42. 连续子数组的最大和方法一:动态规划(推荐使用)知识点:动态规划动态规划算法的基本思想是:将待求解的问题分解成若干个相互联系的子问题,先求解子问题,然后从这些子问题的解得到原问题的解;对于重复出现的子问题,只在第一次遇到的时候对它进行求解,并把答案保存起来,让以后再次遇到时直接引用答案,不必重新求解。动态规划算法将问题的解决方案视为一系列决策的结果。思路:一旦分出一段长度为1的小段,只会减少总长度,还不能增加乘积,因此长度为2的绳子不分比分开的乘积大,长度为3的绳子不分比分开的乘积大,长度为4的绳子分成2*2比较大。前面的我们都可以通过这样递推得到,后面的呢?同样递推!如果我有一个长度为nnn的绳子,我们要怎么确定其分出最大的乘积,我们可以尝试其中一段不可分的为jjj,那么如果另一段n−jn-jn−j最大乘积已知,我们可以遍历所有jjj找到这个最大乘积。因此用dp[i]dp[i]dp[i]表示长度为i的绳子可以被剪出来的最大乘积,那么后续遍历每个jjj的时候,我们取最大dp[i]=max(dp[i],j∗dp[i−j])dp[i] = max(dp[i], j * dp[i - j])dp[i]=max(dp[i],j∗dp[i−j])就好了。//可以被分成两份for(int j = 1; j < i; j++)    //取最大值    dp[i] = max(dp[i], j * dp[i - j]);具体做法:step 1:检查当number不超过3的时候直接计算。step 2:用dp数组表示长度为i的绳子可以被剪出来的最大乘积,初始化前面4个容易推断的。step 3:遍历每个长度,对于每个长度的最大乘积,可以遍历从1到iii的每个固定一段,按照上述公式求的最大值。step 4:最后数组最后一位就是答案。图示:Java实现代码:import java.util.*;public class Solution {    public int cutRope(int target) {        //不超过3直接计算        if(target <= 3)             return target- 1;        //dp[i]表示长度为i的绳子可以被剪出来的最大乘积        int[] dp = new int[target + 1];        dp[1] = 1;        dp[2] = 2;        dp[3] = 3;        dp[4] = 4;        //遍历后续每一个长度        for(int i = 5; i <= target; i++)            //可以被分成两份            for(int j = 1; j < i; j++)                //取最大值                dp[i] = Math.max(dp[i], j * dp[i - j]);        return dp[target];    }}C++实现代码:class Solution {public:    int cutRope(int number) {        //不超过3直接计算        if(number <= 3)             return number - 1;        //dp[i]表示长度为i的绳子可以被剪出来的最大乘积        vector<int> dp(number + 1, 0);        dp[1] = 1;        dp[2] = 2;        dp[3] = 3;        dp[4] = 4;        //遍历后续每一个长度        for(int i = 5; i <= number; i++)            //可以被分成两份            for(int j = 1; j < i; j++)                //取最大值                dp[i] = max(dp[i], j * dp[i - j]);        return dp[number];    }};Python实现代码:class Solution:    def cutRope(self , number: int) -> int:        #不超过3直接计算        if number <= 3:             return number - 1        #dp[i]表示长度为i的绳子可以被剪出来的最大乘积        dp = [0 for i in range(number + 1)]        dp[1] = 1        dp[2] = 2        dp[3] = 3        dp[4] = 4        #遍历后续每一个长度        for i in range(5, number + 1):            #可以被分成各种长度的两份            for j in range(1, i):                #取最大值                dp[i] = max(dp[i], j * dp[i - j])        return dp[number]复杂度分析:时间复杂度:O(n2)O(n^2)O(n2),两层遍历空间复杂度:O(n)O(n)O(n),辅助数组dp的空间方法二:贪心(扩展思路)知识点:贪心贪心思想属于动态规划思想中的一种,其基本原理是找出整体当中给的每个局部子结构的最优解,并且最终将所有的这些局部最优解结合起来形成整体上的一个最优解。思路:根据均值不等式,有:n1+n2+...+nmm≥n1n2...nmm\frac{n_1+n_2+...+n_m}{m}\geq \sqrt[m]{n_1n_2...n_m}mn1​+n2​+...+nm​​≥mn1​n2​...nm​-10,-9.5,-14c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429c69,-144,104.5,-217.7,106.5,-221c5.3,-9.3,12,-14,20,-14H400000v40H845.2724s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z M834 80H400000v40H845z">​,等号当且仅当n1=n2=n3=...nmn_1=n_2=n_3=...n_mn1​=n2​=n3​=...nm​时成立,因为加法部分和是固定的绳子总长度,因此要使乘积最大,应该以相等的长度等分成多段。如果将绳子按照每段长度为xxx等分成mmm段,则n=mxn=mxn=mx,乘积为xmx^mxm,因为有xm=xnx=(x1x)nx^m=x^{\frac{n}{x}}=(x^{\frac{1}{x}})^nxm=xxn​=(xx1​)n,因此当x1xx^{\frac{1}{x}}xx1​取最大值时取最大值。令y=x1xy=x^{\frac{1}{x}}y=xx1​,即求这个函数的极值即可直到绳子等分成长度为多少可以使乘积最大。根据取对数、求导、求极值等一系列数学操作,得驻点为x0=ex_0=ex0​=e,即极大值需要将绳子分成每段e,但是绳子长度只能是整数,靠近e的只有2和3,二者分别代入公式,发现当x=3x=3x=3是,乘积达到最大。因此后续,使用贪心思想,不断将绳子分成每段长度为3即可,不足3的可以考虑,如果最后剩余的是2,直接乘上,如果最后剩余的是1,则取出一个3组成4分成长度为2的两段,因为2∗2>1∗32*2>1*32∗2>1∗3。具体做法:step 1:按照上述思路,不超过3的直接计算step 2:超过3的不断累乘3,然后number不断减去3,直到最后不超过4。step 3:最后乘上剩余的数字。Java实现代码:public class Solution {    public int cutRope(int target) {        //不超过3直接计算        if(target <= 3)             return target - 1;        int res = 1;        while(target > 4){            //连续乘3            res *= 3;             target -= 3;         }        return res * target;       }}C++实现代码:class Solution {public:    int cutRope(int number) {        //不超过3直接计算        if(number <= 3)             return number - 1;        int res = 1;        while(number > 4){            //连续乘3            res *= 3;             number -= 3;         }        return res * number;    }};Python实现代码:class Solution:    def cutRope(self , number: int) -> int:        #不超过3直接计算        if number <= 3:             return number - 1        res = 1        while number > 4:            #连续乘3            res *= 3             number -= 3         return res * number复杂度分析:时间复杂度:O(n)O(n)O(n),其中nnn为绳子的长度,最坏需要计算n/3n/3n/3次空间复杂度:O(1)O(1)O(1),常数级变量,无额外辅助空间
点赞 131
评论 24
全部评论

相关推荐

不愿透露姓名的神秘牛友
05-29 22:21
Offer1:小马智行,深圳,测试开发工程师,17.0k*16.0,Offer2:追觅科技,深圳,嵌入式工程师,18.0k*15.0,
嵌软狗都不学:各位base深圳的同事,作为也是并肩作战的一员,今天想站在管理视角,和大家开诚布公地聊一聊:从近几个月的上下班数据对比看来,我们发现一个明显的差异:深圳同事的在岗时间普遍比苏州同事短。很多深圳同事早上9点之后才到公司,晚上不到 20 点就下班了;而总部那边,20点半甚至 22 点后还有不少同事在办公室忙碌,特别是研发团队,加班更是常态。相信去过苏州的同事,对这种场景都不陌生。我很好奇,这是因为苏州工作任务太重还是咱们深圳同事效率真的高到能在更短时间内完成工作?MOVA在深圳成立分公司是为了吸引更优秀的人才贡献更多更高质的价值,公司管理层给我反馈的是深圳招到的多是行业的专家大拿,大部分都是薪资比苏州高的,而且我们办公的租金等也远高于苏州的..MOVA虽脱胎于强壮的集团母体不久,各业务板块尚未实现全面盈利,虽说公司管理层目光长远,不纠结当下的人才投入,但行业内的普遍标准是,员工创造的价值要达到公司雇佣成本的 15 倍以上。大家不妨自我审视一下,自己是否达到了这个标准?如果是抱着划水、按时打卡走人拿毛爷爷的心态那不适合来MOVA,那样过下去不但自己过得尴尬也会影响MOVA这个大船的攻城略地的速度.我并非鼓励大家盲目加班,而是倡导高效工作,拒绝无效忙碌,不要让项目进度因低效受影响,也别把精力浪费在和苏州同事拼打卡时长上,提倡更高的人效比;考虑到两地地域和交通差异,相信大家会找最适合自己发挥的工作方式(比如按时下班后1小时到家晚饭后继续未竟工作等..)大家在遵守公司规章的情况下尽情地体现自己的能力价值,为MOV!和深圳公司争光我们在这边才能更安心更有信心的工作下去;请客BU长、名部门长、项目管理和各业务单元负责人,全面梳理团队情况,及时评估成员工作负荷与成果质量,坚决清退划水害虫痕疫,践行公司价值观,相互监督,防止管理漏洞及渎职。感谢人家的理解,也请人家多担待我的直言不讳……
点赞 评论 收藏
分享
04-09 09:47
门头沟学院 Java
Arbelite_:2-3k,这工资还不如去摇奶茶
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务