[LeetCode] 343. Integer Break

Given a positive integer n, break it into the sum of at least two positive integers and maximize the product of those integers. Return the maximum product you can get.

Example 1:

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

Example 2:

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

Note: You may assume that n is not less than 2 and not larger than 58.

整数拆分。题意是给一个整数n,请你把它拆分成2个或者更多个正整数,使得拆分下来的数字之间的乘积是最大的

我简单试了几个例子,比如2,只能拆成1x1 = 1,这没什么可说的;3可以拆成1x1x1 = 1但是这毫无意义,拆成1x2 = 2的结果都比它大;4可以拆成1x3 = 3或者2x2 = 4;5可以拆成1x4 = 5或者2x3 = 6;6可以拆成1x5 = 5或者2x4 = 8;7可以拆成1x6 = 6或者2x2x3 = 12;8可以拆成1x7 = 7或者2x2x2x2 = 16。

注意到为了要使乘积更大,首先1xN这种情况肯定不会使乘积更大,那么就试着试一些因数比1大的情形。你会发现乘积比较大的结果,因数总是往2和3上靠近,因为这样可以使得因子更多。同时发现一个数字被分解后得到的最大乘积既然最后总是往2和3靠近,那么这里面就一定有重复计算。我这里找个一张截图解释数字如何拆分,实际上这个题也是可以用动态规划做的。

动态规划的定义是dp[i]表示数字i被拆分后能得到的最大乘积。转移方程是dp[i] = k * (i - k) 或者dp[i] = dp[k] * dp[i - k],0 < k < i

意思是dp值有可能是一个数被拆解成两个数字(小于6的情况),或者是这个数字可以被拆解成更多个因子,只不过是后面第二种情况dp[k] * dp[i - k]事实上是对之前的答案有储存。

时间O(n)

空间O(n)

Java实现

 1 class Solution {
 2     public int integerBreak(int n) {
 3         int[] dp = new int[n + 1];
 4         for (int i = 1; i <= n; i++) {
 5             for (int j = 1; j < i; j++) {
 6                 dp[i] = Math.max(dp[i], (i - j) * j);
 7                 dp[i] = Math.max(dp[i], dp[j] * (i - j));
 8             }
 9         }
10         return dp[n];
11     }
12 }

LeetCode 题目总结

原文地址:https://www.cnblogs.com/cnoodle/p/13401647.html