343. 整数拆分
给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。
1 | 输入: 10 |
这里比较容易出错的是,必须拆分为至少2个正数,而不能不拆分。
动态规划的解法1
先证明一个结论:数字s拆分为两数之和,两数越接近,乘积越大(或者可以说是,周长相同的矩形,越接近正方形,面积越大)。
1 | a + b = s |
定义 f(n)
为数字n可以拆分至少2个得到的最大乘积:
- 拆分为2个时,最大的乘积是
(n/2) * (n - n/2)
。如果n为偶数,两者相等,如果n为奇数,两者相差1。 - 拆分为2个以上,第一个数字选
i
时(0 < i < n
),最大乘积为i * f(n-i)
。
因此:
f(n) = max { (n/2)*(n-n/2), 1*f(n-1), ..., (n-1)*f(1) }
初值:
f(1) = 0
f(2) = 1 (1 + 1)
f(3) = 2 (1 + 2)
于是动态规划解法为:
1 | class Solution { |
动态规划的解法2
证明一个结论:当整数s >= 4
时,s拆分为至少2个数字的最大乘积,一定大于等于s(即不拆分)。
1 | 设 s = p + q,且p,q均为正整数 |
定义 f(n)
为数字n拆分得到的最大乘积,而g(n)
为数字n拆分或不拆分得到的最大乘积:
g(n) = max { n, 1*g(n-1), ... (n-1)*g(1) }
当 n >= 4
时,必须要拆分才能得到最大值(等于4时可拆可不拆),因此上式max中的第一项n可以省去,且f(n) = g(n)
,于是:
f(n) = g(n) = max { 1*g(n-1), ..., (n-1)*g(1) }
最后使用动态规划实现如下:
1 | class Solution { |
数学解法
这道题也可以用纯数学解法,性能更好,可参考 题解