【Leetcode】343. Integer Break

题目地址:

https://leetcode.com/problems/integer-break/

给定一个正整数,将其进行切割,要求至少切割成两个数,使得切割出来的所有数乘积最大,问这个最大乘积是多少。

这是一道数论题。(并不需要微积分,微积分能给出一个大体想法,但很难非常严格的说清楚,其实基本的数论知识已经足够了。)

首先,如果拆分出来的数中有一个大于 4 4 4,不妨设这个数是 n n n那么有 2 ( n − 2 ) > n 2(n-2)>n 2(n2)>n,所以可以继续拆分这个 n n n 2 + ( n − 2 ) 2+(n-2) 2+(n2)从而获得更大的乘积。所以所有拆分出来的数字必须是 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 222<33,这样就得到了更大的数,所以拆分出来的 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 n22,接下来我们分三种情况讨论:(以下的” / / /“都代表计算机里的整除,而非数学里的除法)
1、若 n ≡ 0 ( m o d    3 ) n\equiv 0 (\mod 3) n0(mod3),则由于 n 2 ≤ 2 n_2\le 2 n22,所以必然有 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) n1(mod3),此时 n 2 = 2 n_2=2 n2=2,所以 n 3 = n / 3 − 1 n_3=n/3-1 n3=n/31
3、若 n ≡ 2 ( m o d    3 ) n\equiv 2 (\mod 3) n2(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(nk)>n,有 n > k 2 k − 1 n>\frac{k^2}{k-1} n>k1k2我们需要右边的数尽量小,只有右边的数尽量小,我们才有可能让 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 k1k2=k1+k11+221 +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后乘积几乎一定会变大。这里只是用数学的语言说明一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值