传送门 :https://leetcode-cn.com/problems/integer-break/
题目
给定一个正整数 n
,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。
示例 1:
输入: 2 输出: 1 解释: 2 = 1 + 1, 1 × 1 = 1。
示例 2:
输入: 10 输出: 36 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
说明:你可以假设 n
不小于 2
且不大于 58
。
解题思路:动态规划
对于的正整数 ,当 时,可以拆分成至少两个正整数的和。令 是拆分出的第一个正整数,则剩下的部分是 ,其中 可以选择不拆或者继续拆分。
- 不拆:`dp[i]=j×(i-j)`
- 拆分:`dp[i]=j×dp[i-j]`
令 表示为将正整数 拆分成至少两个正整数的和之后的最大乘积。 [ 即题目的要求 ]
状态转移方程:
最终得到答案 的值即为将正整数 拆分成至少两个正整数的和之后,这些正整数的最大乘积。
边界情况:0
不是正整数,1
是最小的正整数,0
和 1
都不能拆分,因此 。
复杂度分析
时间复杂度:
其中 是给定的正整数。对于 2
到 n
的每个整数都要计算对应的dp[i]
,计算一个整数对应的 dp
值需要 O(n)
的时间复杂度,因此总时间复杂度是
空间复杂度:
其中 是给定的正整数。创建一个数组 dp
,返回长度为 n+1
代码
官方代码
class Solution {
public int integerBreak(int n) {
int[] dp = new int[n + 1];
for (int i = 2; i <= n; i++) {
for (int j = 1; j < i; j++) {
dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j]));
}
}
return dp[n];
}
}