剑指offer剪绳子

这篇博客介绍了如何解决绳子剪辑问题以获得最大乘积,提供了两种解题思路:动态规划和找规律法。动态规划通过自底向上的方式记录每个长度绳子的最大乘积,避免重复计算。找规律法则通过观察3的个数对乘积的影响来优化解题。示例展示了不同长度绳子的最大乘积计算过程。
摘要由CSDN通过智能技术生成

剪绳子
题目描述:给你一根长度为 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

解题思路:
思路一:动态规划

我们根据题目要求知道,这条绳子是必须要剪的,当绳子长度小于2时就不能剪,必须返回,当剩余绳子长度为2时,如果我们再继续剪一刀就会变成1和1,这样他们的乘积就是1,小于原来长度2,如果剩余绳子长度为3时,如果再剪一刀,就会变成1和2,他们的乘积就是2,小于原来长度3,所以,当剩余绳子长度小于4时,我们就不能继续剪。假设一刀将绳子剪为i和n-i,那么最大乘积就是F(n)=F(i)*F(n-i),F(x)代表的是,绳子长度为x时的最大乘积。但是这个式子是一个从上到下的递归式,其中包含大量的重复计算,所以我们需要从下往上记录,我们定义一个数组cnt用来记录当绳长为下标长度时的最大乘积(值)。

class Solution {
public:
    int cuttingRope(int n) {
        if(n<4)return n-1;
        vector<int>cnt(n+1,0);//多开一个空间,用来存放绳子长度为0的情况
        //下面这些不是说当绳子长度为0,1,2,3时他们的最大乘积是0,1,2,3
        //而是,指如果绳子剩下1,2,3后他们就不在继续剪了,假如剩下绳长为3时,如果在继续剪一刀,那么就会变成1和2,1和2的乘积是2小于3,所以当绳长剩余0,1,2,3时就不剪了。
        cnt[1]=1;
        cnt[2]=2;
        cnt[3]=3;
        for(int i=4;i<=n;++i)
        {
            int maxVal=0;
            for(int j=1;j<=i/2;++j)//代表的是剩余绳长从4开始,那么可以继续剪,最开始剪去长度为1的绳子,算出最大乘积,然后在剪去J++de绳子,再继续算最大乘积。
            //为什么j<i/2呢?是因为剪去一半以后再继续剪,就会和之前的结果是一样的。
            {
                maxVal=max(maxVal,cnt[j]*cnt[i-j]);
            }
            cnt[i]=maxVal;
        }
        return cnt[n];
    }
};
思路二:找规律法

我们发现当绳子分的长度中3的个数更多的时候,最后的结果就会更大。综上有以下代码:

class Solution {
public:
    int cuttingRope(int n) {
       if(n<4)return n-1;
       int a=n/3,b=n%3;
       if(b==0)return a=pow(3,a);
       if(b==1)return a=pow(3,a-1)*4;
       if(b==2)return a=pow(3,a)*2;
       return a;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值