Python3——剑指Offer 14-I. 剪绳子

一、题目描述
题目来自剑指Offer 14-I ,难度中等。

给你一根长度为 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 <= n <= 58

二、题目解析

  1. 长度为n的绳子,切成m段,要求这m段的最大乘积,可以先从长度比n小的绳子转移来。先算出长度为2的绳子的最大乘积,再算长度为3的,以此类推,直到长度为n。
  2. 用一个dp数组记录 从2到n长度的绳子剪掉后的最大乘积。我们设 i 为当前的绳子长度,dp [ i ] 为绳子乘积的最大值。因为初始dp[2]=1,那么 i 从长度为3的绳子开始,取值范围为 [ 3 , n ] 。
  3. 对长度为 i 的绳子,先剪掉第一段长度为 j ,那么剩下的绳子长度为( i - j )。
  4. 对于剪掉的第一段绳子 j , 它的长度一定不是1,因为1对后面的乘积没有任何增益效果,所以 j 取值范围为 [ 2 , i )。
  5. 对于剩下的绳子 i - j ,它可以剪也可以不剪。
    如果不剪的话,那么乘积为 j * ( i - j)。
    如果剪的话,那么乘积为 j * dp[ i - j ]。
    取两中情况的最大值,即 max( j * ( i - j), j * dp[ i - j ] )。
  6. 对长度为 i 的绳子,对其所有 j 不同的情况取最大值,因此可得到 dp[ i ]转移方程为
    dp [ i ] = max( dp [ i ] , max( j * ( i - j), j * dp[ i - j ] )。
  7. 最后返回 dp [ n ] 即可。

在这里插入图片描述
三、参考代码

class Solution:
    def cuttingRope(self, n: int) -> int:
        #用一个名为 dp 的数组来记录从 0 到 n 长度的绳子剪掉后的最大乘积
        #默认都是0
        dp = [0 for _ in range(n+1)]

        #由于绳子必须被剪,所以长度为 2 的绳子只有剪成1和1两段,乘积结果为1
        dp[2] = 1

        #从长度大于等于3的绳子才开始进入讨论范围
        #从长度为3的绳子开始考虑,讨论它的最大乘积是多少,并不断延伸绳子长度
        for i in range(3,n+1):
            #对于长度为i的绳子,它可以分为两个区间 j 和 i-j
            #j的范围由2开始,因为剪成1的绳子无法扩大乘积的值
            #j可以延伸到i-1
            for j in range(2,i):
                #不剪总长度乘积为 j*(i-j)
                #剪的话长度乘积为 j*dp[i-j]
                #取两者的最大值,即 Max(j*(i-j),j*dp[i-j]) 
                #那么此时 dp[i]的值取i不剪的值dp[i]和剪的值Max(j*(i-j),j*dp[i-j])这两者的最大值
                #而j有不同种情况,则每次的dp[i]会不同
                #状态转移方程为dp[i] = max(dp[i],max(j*(i-j),j*dp[i-j]))
                #比如一开始,i=3,j=2
                #dp[3]=max[0,max(2*1,2*dp[1])]
                #     =max[0,max(2,2)]
                #     =2
                dp[i] = max(dp[i],max(j*(i-j),j*dp[i-j]))

        return dp[n]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值