剑指offer题解(C语言)----JZ14 剪绳子

题目

给你一根长度为 n 的绳子,请把绳子剪成整数长的 m 段( m、n 都是整数,n > 1 并且 m > 1 , m <= n ),每段绳子的长度记为 k[1],...,k[m] 。请问 k[1]*k[2]*...*k[m] 可能的最大乘积是多少?如当绳子的长度是 8 时,我们把它剪成长度分别为 2、3、3 的三段,此时得到的最大乘积为18。

数据范围: 2≤n≤60
进阶:空间复杂度O(1) ,时间复杂度O(n)

解析

其实这应该算作一个数学问题,因为题目考察的能力和算法没有什么很大关联,还是考察基础数学的内容较多。

核心思想其实有两条:

1. 和一定,差小积大。也就是我们需要寻找到尽量多的、相等或相差为1的数,这样的乘积最大;

2. 3+3=2+2+2;3*3 > 2*2*2。

核心思想中其实不难发现,如果要寻找尽量多的数,则作为因子数的数就要尽量小,如2,3,4,5等等,又因为4可以分解为2+2=2*2,所以4的本质就是2;5=2+3,可以拆解为更小的单位,且2*3>5,因此我们将目标锁定在 2 和 3 上。

究竟要选2还是3呢?根据核心思想2,可以发现和相同的情况下,用3的乘积比2的要大,因此我们在分解和数的时候要尽量用3分解。

任意一个分解数number只会服从下列一种情况:

1. number是3的倍数,那么乘积自然而然就是将number中的所有3相乘即可;

2. number除3余1,这时候需要考虑将分解出来的最后一个3另作考虑,即3*1与2*2哪个更大, 显而易见是后者。因此number除3余1时,需要将最后一个3拿出来和1配成2个2另作考虑;

3. number除3余2,乘积则为所有的3相乘后再乘2;

代码

int cutRope(int number ) {
    int iThreeNum = 0; //分解数中包含3的个数
    int iTwoNum = 0; //分解数种包含2的个数
     
    if (3 >= number) //如果绳长为2或3,只能分解为1*(number-1)的形式
        return number - 1; //返回乘积
     
    iThreeNum = number / 3; //为了有尽量多的3,则先将number中的3减干净
    if (1 == (number % 3)) //如果number除3余1
    {
        iThreeNum--; //则将3的个数-1,将3+1变为2+2
    }
    iTwoNum = (number - 3 * iThreeNum) / 2; //减掉所有3之后,剩下的就只有2或1,1可以忽略,所以直接除2就是2的个数
     
    return (int)(pow(3, iThreeNum) * pow(2, iTwoNum)); //利用乘方计算最终的乘积
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值