整数拆分
题目描述
给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。
解题思路
1. 动态规划
设
d
p
[
i
]
dp[i]
dp[i] 表示正整数
i
i
i,被拆分为至少两个正整数后的最大乘积。
那么
d
p
[
0
]
=
d
p
[
1
]
=
0
dp[0] = dp[1] = 0
dp[0]=dp[1]=0
假设
i
i
i首先可以拆成
j
j
j。则有以下两种情况:
- 将 i i i分为 j j j和 i − j i-j i−j的,且 i − j i-j i−j不能再被分了。此时的乘积就是 j × ( i − j ) j×(i-j) j×(i−j)
- 将
i
i
i 拆分成
j
j
j和
i
−
j
i-j
i−j的和,且
i
−
j
i−j
i−j 继续拆分成多个正整数,此时的乘积是
j
×
d
p
[
i
−
j
]
j×dp[i−j]
j×dp[i−j]
所以, d p [ i ] = m a x ( j × ( i − j ) , j × d p [ i − j ] ) dp[i] =max(j×(i-j),j×dp[i-j]) dp[i]=max(j×(i−j),j×dp[i−j])。因为j的范围为 ( 1 , i − 1 ) (1,i-1) (1,i−1), 所以需要遍历j求最大的dp[i]。
动态转移方程如下:
dp [ i ] = max 1 ≤ j < i { max ( j × ( i − j ) , j × d p [ i − j ] ) } \operatorname{dp}[i]=\max _{1 \leq j<i}\{\max (j \times(i-j), j \times \mathrm{dp}[i-j])\} dp[i]=1≤j<imax{max(j×(i−j),j×dp[i−j])}
def integerBreak(self, n: int) -> int:
dp = [0 for i in range(n+1)]
# print(dp)
for i in range(2,n+1):
for j in range(1,i):
dp[i] = max(dp[i],j * (i-j),j * dp[i-j])
return dp[n]
总结:时间复杂度为O(n^2),不咋优秀
2. 用数学方法解题
有推论:将数字n尽可能以因子3等分时,乘积最大。
推理的具体过程见链接: https://leetcode-cn.com/problems/integer-break/solution/343-zheng-shu-chai-fen-tan-xin-by-jyd/.
还没写完。。。
references
[1] https://leetcode-cn.com/problems/integer-break/solution/343-zheng-shu-chai-fen-tan-xin-by-jyd/.
[2] https://leetcode-cn.com/problems/integer-break/