剑指 Offer 14- I. 剪绳子

Posted 炫云云

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指 Offer 14- I. 剪绳子相关的知识,希望对你有一定的参考价值。

剑指 Offer 14- I. 剪绳子

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

动态规划

对于的正整数 n,当 n ≥ 2 n \\ge 2 n2 时,可以拆分成至少两个正整数的和。令 k k k 是拆分出的第一个正整数,则剩下的部分是 n − k n-k nk n − k n-k nk 可以不继续拆分,或者继续拆分成至少两个正整数的和。由于每个正整数对应的最大乘积取决于比它小的正整数对应的最大乘积,因此可以使用动态规划求解。

创建数组 dp \\textit{dp} dp​ ,其中 dp [ i ] \\textit{dp}[i] dp[i] 表示将正整数 i i i 拆分成至少两个正整数的和之后,这些正整数的最大乘积。特别地,0 不是正整数,1 是最小的正整数,0 和 1 都不能拆分,因此 dp [ 0 ] = dp [ 1 ] = 0 \\textit{dp}[0]=\\textit{dp}[1]=0 dp[0]=dp[1]=0

i ≥ 2 i \\ge 2 i2 时,假设对正整数 i i i​ 拆分出的第一个正整数是 j j j 1 ≤ j < i 1 \\le j < i 1j<i ),则有以下两种方案:

  • i i i 拆分成 j j j i − j i-j ij 的和,且 i − j i-j ij​ 不再拆分成多个正整数,此时的乘积是 j × ( i − j ) j \\times (i-j) j×(ij)
  • i i i 拆分成 j j j​ 和 i − j i-j ij 的和,且 i − j i-j ij​ 继续拆分成多个正整数,此时的乘积是 j × dp [ i − j ] j \\times \\textit{dp}[i-j] j×dp[ij]

因此,当 j j j 固定时,有 dp [ i ] = max ⁡ ( j × ( i − j ) , j × dp [ i − j ] ) \\textit{dp}[i]=\\max(j \\times (i-j), j \\times \\textit{dp}[i-j]) dp[i]=max(j×(ij),j×dp[ij]) 。由于 j j j 的取值范围是 1 到 i − 1 i-1 i1 ,需要遍历所有的 j j j 得到 dp [ i ] \\textit{dp}[i] dp[i] 的最大值,因此可以得到状态转移方程如下:

dp [ i ] = max ⁡ 1 ≤ j < i { max ⁡ ( j × ( i − j ) , j × dp [ i − j ] ) } \\textit{dp}[i]=\\mathop{\\max}\\limits_{1 \\le j < i}\\{\\max(j \\times (i-j), j \\times \\textit{dp}[i-j])\\} dp[i]=1j<imax{max(j×(ij),j×dp[ij])}
最终得到 dp [ n ] \\textit{dp}[n] dp[n] 的值即为将正整数 n n n 拆分成至少两个正整数的和之后,这些正整数的最大乘积。

class Solution(object):
    def cuttingRope(self, n):
        """
        :type n: int
        :rtype: int
        """
        dp = [0] * (n + 1)
        for i in range(2, n+1):
            for j in range(i):
                dp[i] = max(dp[i],j *(i-j), j*dp[i-j])
        return dp[n]

参考

Krahets - 力扣(LeetCode) (leetcode-cn.com)

以上是关于剑指 Offer 14- I. 剪绳子的主要内容,如果未能解决你的问题,请参考以下文章

剑指 Offer 14- I. 剪绳子

剑指OFFER----面试题14- I. 剪绳子

速看,双100%剑指 Offer 14- I. 剪绳子 I

剑指Offer面试题14- I. 剪绳子

剑指 Offer 14- I. 剪绳子(C++暴力+动态规划贪心解)

[LeetCode]剑指 Offer 14- I. 剪绳子