剑指offer 14 - 剪绳子Ⅰ - python

题目描述:

给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k [ 0 ] , k [ 1 ] , . . . , k [ m ] k[0],k[1],...,k[m] k[0],k[1],...,k[m]。请问 k [ 0 ] × k [ 1 ] × . . . × k [ m ] k[0] \times k[1] \times ... \times k[m] k[0]×k[1]×...×k[m]可能的最大乘积是多少?例如,当绳子的长度是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


贪心算法

对于长度为 n n n的绳子要是剪成 m m m段后,段长度的乘积最大。首先我们先来观察一下简单的情形:

  • n = 0 n = 0 n=0时,自然为0
  • n = 1 n=1 n=1时,无法分割,结果为 1
  • n = 2 n=2 n=2时,可以分成1 + 1,结果为 1
  • n = 3 n = 3 n=3时,可以分为1 + 2,结果为 2
  • n = 4 n=4 n=4时,可以分成 2 + 2,结果为4
  • n = 5 n = 5 n=5时,可以分成 2 + 3,结果为6

而且依次往后列举不同输入时的情况,每个 n n n分割后都是2和3的组合。因此,为了使乘积最大,我们要尽可能的剪成长度为3的段,然后才是长度为2的段,而且剪完后的结果都是2和3。假设长度为2有 x x x,长度为3有 y y y,那么乘积就等于 2 x × 3 y 2^x \times 3^y 2x×3y

class Solution:
    def cuttingRope(self, n: int) -> int:
        if n == 0: return 0
        if n == 1 or n == 2: return 1
        if n == 3: return 2

        countOfThree = n // 3  # 长度为3最多能剪多少段
        if n - countOfThree * 3 == 1:  # 如果除去长度为3的长度为1,则需要少剪一次
            countOfThree -= 1
        
        countOfTwo = (n - countOfThree * 3) // 2 # 长度为2的有多少段

        return pow(3, countOfThree) * pow(2, countOfTwo)

动态规划

按照从下而上的顺序计算,先得到f(2),f(3),再计算f(4),f(5), f ( n ) = m a x ( f ( i ) × f ( n − i ) ) , 0 < i < n f(n)=max(f(i) \times f(n-i)),0<i<n f(n)=max(f(i)×f(ni)),0<i<n

class Solution:
    def cuttingRope(self, n: int) -> int:
        dp = [0] * (n + 1)
        dp[1] = 1

        for i in range(2, n + 1):
            for j in range(1, i):
                tmp = max(j, dp[j]) * max(i - j, dp[i - j])
                dp[i] = max(dp[i], tmp)
        return dp[-1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值