[LeetCode] 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

整数拆分。

题意是给一个整数 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 题目总结

posted @ 2020-07-30 02:51  CNoodle  阅读(153)  评论(0编辑  收藏  举报