【LeetCode】面试题14-1. 剪绳子

题目:

思路:

1、如果m是确定值,则这m段越平均它们的乘积越大(数学直觉)。所以遍历所有的M(最小2段,最大n段),计算当前m下的最大值,然后对比得到所有M下的最大值。
2、不需要遍历所有的M,根据如下两条数学推论直接计算最大值

  • 将绳子以相等的长度等分为多段,得到的乘积最大。
  • 尽可能将绳子以长度3等分为多段时,乘积最大。
    • 当n<=3时,按照规则不切分。但题目要求必须切分(m>1),所以返回n-1
    • 当n>3时,求n除以3的整数部分a和余数b(n=3a+b),则
      • b=0,直接返回3^a

      • b=1,乘以1和没乘一样,所以将一个3拿出来和1一起分成两个2,返回4x3^(a-1)

      • b=2,返回2x3^a

3、动态规划,对长度为n的绳子进行切割,可以划分成子问题(最优子结构、无后向性、重叠子问题)。递归函数为F(n)=max(i x (n-i), i x F(n-i)), i=1, 2, ..., n-2

代码:

Python

import math
class Solution(object):
    def cuttingRope(self, n):
        """
        :type n: int
        :rtype: int
        """
        # # 暴力搜索M切分段数,对每次切分尽量平分
        # res = 0
        # for i in range(2, n+1):
        #     a = n // i
        #     b = n % i
        #     tmp = math.pow(a, i - b) * math.pow(a + 1, b)
        #     if tmp > res:
        #         res = int(tmp)
        # return res
        
        # # 尽量平分,使得每段长度为3
        # if n <= 3:
        #     return n - 1
        # a = n // 3
        # b = n % 3
        # if b == 0:
        #     return int(math.pow(3, a))
        # if b == 1:
        #     return 4 * int(math.pow(3, a - 1))
        # if b == 2:
        #     return 2 * int(math.pow(3, a))

        # 动态规划
        dp = [0 for _ in range(n + 1)]
        dp[1] = 1
        dp[2] = 1
        for i in range(3, n + 1):  # 当前绳子长度为i
            for j in range(1, i):  # 第一刀切分长度
                dp[i] = max(dp[i], j * (i - j), j * dp[i - j])
        return dp[n]

相关问题

posted @ 2020-05-26 10:40  一只背影  阅读(271)  评论(0编辑  收藏  举报