剪绳子

题目描述

给你一根长度为 n n n 的绳子,请把绳子剪成 m m m ( m , n 都 是 整 数 , 2 ≤ n ≤ 58 并 且 m ≥ 2 ) (m,n都是整数,2 \leq n \leq 58 并且 m \geq 2) (m,n2n58m2) 。每段的绳子的长度记为k[0]、k[1]、k[2]、……、k[m-1]。k[0]k[1]k[2]……k[m-1]可能的最大乘积是多少?

样例
Input: 8
Output:  18
// 当绳子长度为8时,将其剪成长度分别为2,3,3的三段,此时得到最大乘积18。

解题思路

  • 描述

    这里有一个推导——为满足最大乘积尽可能的大,需将n尽可能分成多的3,同时如果n%3 == 1则分为两个2。

    证明如下:(假定 n > 0 ,n = n1 + n2 + …… + nk)

    1. 假定存在 n i ≥ 5 ni \geq 5 ni5,则有 3 × ( n i − 3 ) ≥ n i 3 \times (ni - 3) \geq ni 3×(ni3)ni。那么最大乘积要尽可能大,ni一定小于5。
    2. 对于 n i = 4 ni = 4 ni=4 4 = 2 × 2 4 = 2 \times 2 4=2×2。那么对于4等价于两个2相乘。
    3. 不可能存在ni = 1的情况,因为ni对乘积毫无影响。
    4. 假设存在3个及其以上的2,由于 2 × 2 × 2 &lt; 3 × 3 2 \times 2 \times 2 &lt; 3 \times 3 2×2×2<3×3,那么2的数量只可能最多是两个。
  • 实现代码:

    int maxProductAfterCutting(int length)
    {
    	if (length <= 3)
    	{
    		return 1 * (length - 1);
    	}
    
    	int result = 1;
    	if (length % 3 == 1)
    	{
    		result *= (2 * 2);
    		length -= 4;
    	}
    	else if(length % 3 == 2)
    	{
    		result *= 2;
    		length -= 2;
    	}
    
    	while (length)
    	{
    		result *= 3;
    		length = length - 3;
    	}
    
    	return result;
    }
    
  • 复杂度分析

    时间复杂度: ≈ O ( n ) \approx O(n) O(n)

    空间复杂度: O ( 1 ) O(1) O(1)

    ​ 使用辅助变量result

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值