本题可以抽象为整数划分的问题,给我们一个整数,然后我们把它拆分为更小的若干个正整数的和,使得拆分出来的这些正整数乘积最大。
结论:将整数N把它分成尽量多的3,如果最后剩下一个2的话,就拆分出来一个2,如果剩下两个2的话就拆分为两个2。如果N%3==0,那就把它拆分为若干个3,如果N%3==1,先拆出两个2,剩下的全部分成3,如果N%3==2,先拆出一个2,剩下的全部分成3。下面给出证明:
N > 0, N = n1 + n2 + ... + nk (假设此时拆出的各个元素,使得最大乘积最大)
(1)假设ni >= 5,我们可以划分出一个3,此时,3 * (ni - 3) 是否一定大于ni呢?
3 * ni - 9 >= ni ? ===> 2 * ni >= 9? 是的,因为ni >= 5。所以,如果ni >= 5,我们从中拆出一个3,那么3 * (ni - 3) >= ni,也就是说,拆完3之后一定是比原来更好的。最优解中如果有>= 5的数,那么最优解中一定包含2、3、4了。
(2)如果ni = 4的话,我们可以把它拆成2 * 2,此时乘积不变,所以最优解中也一定不包含4,那么只包含2和3了。
(3)接着证明这里面最多有两个2。假设这里面有三个2,由于2 * 2 * 2 < 3 * 3,所以这里面也一定不会有>= 3个2,那我们就证明了这里面最多有两个2。那就分为三种情况,模3余1时,两个2,模3余2时,一个2,模3余0时,没有2。
(4)显然不包含1,因为拆出一个1来不会使乘积变大。
class Solution {
public:
int maxProductAfterCutting(int length) {
if (length <= 3) return 1 * (length - 1);
int res = 1;
if (length % 3 == 1) res *= 4, length -= 4;
if (length % 3 == 2) res *= 2, length -= 2;
while (length) res *= 3, length -= 3;
return res;
}
};