343. 求分解整数的乘积最大化Integer Break

Posted AI架构师易筋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了343. 求分解整数的乘积最大化Integer Break相关的知识,希望对你有一定的参考价值。

343. Integer Break

Given an integer n, break it into the sum of k positive integers, where k >= 2, and maximize the product of those integers.

Return the maximum product you can get.

Example 1:

Input: n = 2
Output: 1
Explanation: 2 = 1 + 1, 1 × 1 = 1.

Example 2:

Input: n = 10
Output: 36
Explanation: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36.

Constraints:

  • 2 <= n <= 58

1. 分左右两部分的乘积,动态规划

注意左右是指当前这个数,也可能是以前的乘积。动态规划子公式为 maxProduct = max(maxProduct, max(l, dp[l]) * max(r, dp[r]))

比如:要找到 8 的最大乘积,请将 8 分解为两项之和(使第一项小于或等于第二项以防止冗余):

1 + 7 --> 1 * 7 = 7
2 + 6 --> 2 * 6 = 12
3 + 5 --> 3 * 5 = 15
4 + 4 --> 4 * 4 = 16

由此看来,最大乘积为 16,但是我们忽略了将这两个术语中的每一个分解为更多术语,并检查所有这些。让我们将 6 分解为 3 + 3

2 + 6 = 2 + 3 + 3 --> 2 * 3 * 3 = 18

最终成为正确答案。但另一种方法是重用之前计算的 6 的最大乘积,我们知道它是 9:

2 * (3 * 3) = 2 * max_product_of_6 = 2 * 9 = 18

因此,对于 l <= rl + r = n 的 l 和 r的每个选择,检查 l * r 但还要检查先前计算的最大乘积 dp[l] 和 dp[r] 是否大于 l 和 r。从 n = 1 开始,一直到最后的 n。将先前计算的值存储在 dp 列表中。

class Solution:
    def integerBreak(self, n: int) -> int:
        dp = [0, 0]
        for m in range(2, n+1):
            l = 1
            r = m - 1
            maxProduct = 0
            while l <= r:
                maxProduct = max(maxProduct, max(l, dp[l]) * max(r, dp[r]))
                l += 1
                r -= 1
            dp.append(maxProduct)
        return dp[-1]

2. table找规律法

我看到很多解决方案都是指 2 和 3 的因数。但是为什么这两个神奇的数字呢?为什么其他因素不起作用?

如果最优产品包含一个因子f >= 4,那么您可以用因子替换它2f-2,而不会失去最优性,如2*(f-2) = 2f-4 >= f。因此,您永远不需要大于或等于 4 的因子,这意味着您只需要因子 123(而 1 当然是浪费的,您只会将它用于需要它的 n=2 和 n=3) .

其余的我同意,3*32*2*2 好,所以你永远不会使用 2 超过两次。


显然,e不是整数,因此出于这个问题的目的,我们不能将 n 分成e组。然而,这个结果给了我们直觉,因为 2 < e < 3 ,所以只要有可能,n 应该被分成 2 和3。

我们从处理 n 的前几个案例开始,并尝试识别一个模式:

我们可以从这张表中推断出很多东西。首先,一个 DP 解决方案突然出现在我们面前。令 dp[n] 为整数 n 的最大可能乘积。从 n=7 开始,我们注意到 dp[n] = 3*dp[n-3]。我们得到以下O(n)解:

class Solution:
    def integerBreak(self, n: int) -> int:
        predp = [0, 0, 1, 2, 4, 6, 9]
        if n < 7:
            return predp[n]
        dp = predp + [0] * (n - 6)
        for i in range(7, n+1):
            dp[i] = 3 * dp[i-3]
        return dp[-1]

(注意:我们包括了 n=0 和 n=1 的无效输入的基本情况,以保持 dp 索引的对齐,避免需要偏移量。)

参考

https://leetcode.com/problems/integer-break/discuss/383679/Python-DP-solution-with-detailed-explanation.-Avoids-confusion-about-factors-of-2-or-3.

https://leetcode.com/problems/integer-break/discuss/80721/Why-factor-2-or-3-The-math-behind-this-problem.

https://leetcode.com/problems/integer-break/discuss/285876/Python-O(1)-one-line-solution-detailed-explanation

以上是关于343. 求分解整数的乘积最大化Integer Break的主要内容,如果未能解决你的问题,请参考以下文章

343 Integer Break 整数拆分

[Math_Medium]343. Integer Break

343. 整数拆分

LeetCode 343. 整数拆分 | Python

[刷题] 343 Integer Break

LeetCode 343.整数拆分 - JavaScript