题目地址:
https://leetcode.com/problems/integer-break/
给定一个正整数,将其进行切割,要求至少切割成两个数,使得切割出来的所有数乘积最大,问这个最大乘积是多少。
这是一道数论题。(并不需要微积分,微积分能给出一个大体想法,但很难非常严格的说清楚,其实基本的数论知识已经足够了。)
首先,如果拆分出来的数中有一个大于 4 4 4,不妨设这个数是 n n n那么有 2 ( n − 2 ) > n 2(n-2)>n 2(n−2)>n,所以可以继续拆分这个 n n n为 2 + ( n − 2 ) 2+(n-2) 2+(n−2)从而获得更大的乘积。所以所有拆分出来的数字必须是 1 1 1, 2 2 2或者 3 3 3。而拆分出 1 1 1这种情况,乘积一定是比原数要小的,所以只能是不得不拆的情况才会拆分出 1 1 1,也就是当 n = 2 n=2 n=2或者 3 3 3的时候,这两个数需要特判。别的数就一定不会拆分出 1 1 1了。接下来,我们可以证明拆分出来的 2 2 2的个数一定不会大于两个,否则由于 2 + 2 + 2 = 3 + 3 2+2+2=3+3 2+2+2=3+3而 2 ∗ 2 ∗ 2 < 3 ∗ 3 2*2*2<3*3 2∗2∗2<3∗3,这样就得到了更大的数,所以拆分出来的 2 2 2的个数只能是 0 0 0, 1 1 1或者 2 2 2。
设
n
=
2
n
2
+
3
n
3
n=2n_2+3n_3
n=2n2+3n3,其中
n
2
n_2
n2和
n
3
n_3
n3代表
2
2
2和
3
3
3各自的个数。由于
n
2
≤
2
n_2\le 2
n2≤2,接下来我们分三种情况讨论:(以下的”
/
/
/“都代表计算机里的整除,而非数学里的除法)
1、若
n
≡
0
(
m
o
d
3
)
n\equiv 0 (\mod 3)
n≡0(mod3),则由于
n
2
≤
2
n_2\le 2
n2≤2,所以必然有
n
2
=
0
n_2=0
n2=0,所以
n
3
=
n
/
3
n_3=n/3
n3=n/3;
2、若
n
≡
1
(
m
o
d
3
)
n\equiv 1 (\mod 3)
n≡1(mod3),此时
n
2
=
2
n_2=2
n2=2,所以
n
3
=
n
/
3
−
1
n_3=n/3-1
n3=n/3−1;
3、若
n
≡
2
(
m
o
d
3
)
n\equiv 2 (\mod 3)
n≡2(mod3),此时
n
2
=
1
n_2=1
n2=1,所以
n
3
=
n
/
3
n_3=n/3
n3=n/3。
所以算法里只需要根据这三种情况把
n
2
n_2
n2和
n
3
n_3
n3算出来再乘起来即可。代码如下:
public class Solution {
public int integerBreak(int n) {
// 特判一下2和3,这两个数是唯二的需要拆分出1的数
if (n == 2) {
return 1;
}
if (n == 3) {
return 2;
}
int twos = 0, threes = 0;
// 对n进行分类
if (n % 3 == 0) {
threes = n / 3;
} else if (n % 3 == 1) {
threes = n / 3 - 1;
twos = 2;
} else {
threes = n / 3;
twos = 1;
}
int res = 1;
res <<= twos;
for (int i = 0; i < threes; i++) {
res *= 3;
}
return res;
}
}
时间复杂度 O ( log n ) O(\log n) O(logn),空间 O ( 1 ) O(1) O(1)。
至于上面的那个”大于 4 4 4“是怎么想到的呢?
思维过程是这样的:首先我们想得到拆分出的数字的一个上界,我们只需要找到一个临界的数,继续拆分下去有可能会变大即可。设某数 n n n继续拆分下去可以变大,接下来解不等式 k ( n − k ) > n k(n-k)>n k(n−k)>n,有 n > k 2 k − 1 n>\frac{k^2}{k-1} n>k−1k2我们需要右边的数尽量小,只有右边的数尽量小,我们才有可能让 n n n也尽量小,也就会得到那个临界值。因为 k 2 k − 1 = k − 1 + 1 k − 1 + 2 ≥ 2 1 + 2 = 4 \frac{k^2}{k-1}=k-1+\frac{1}{k-1}+2\ge 2\sqrt{1}+2=4 k−1k2=k−1+k−11+2≥21+2=4且在 k = 2 k=2 k=2的时候取到等号,对于 k = 2 k=2 k=2我们解出 n > 4 n>4 n>4,所以所有大于 4 4 4的数都是不能出现在拆分的数里的。有了这个结论,剩余的推理就非常简单了。当然拆分出 2 2 2未必需要这么复杂的推理。因为非常明显,拆分出 2 2 2后乘积几乎一定会变大。这里只是用数学的语言说明一下。