【Golang】LeetCode-剑指Offer-面试题14- I-剪绳子【两种写法】

题目

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

示例 1:

输入: 2 输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1

示例 2:

输入: 10 输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36

提示:

2 <= n <= 58

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/jian-sheng-zi-lcof


解题思路

解题思路引用自作者:jyd

  • 若切分方案合理,绳子段切分的越多,乘积越大。

    • 总体上看,貌似长绳子切分为越多段乘积越大,但其实到某个长度分界点后,乘积到达最大值,就不应再切分了。
  • 问题转化:是否有优先级最高的长度 xx 存在?若有,则应该尽可能把绳子以 xx 长度切为多段,以获取最大乘积。

  • 为使乘积最大,只有长度为 2 和 3 的绳子不应再切分,且 3 比 2 更优 (详情见下表)
    在这里插入图片描述


算法流程

  • 贪心规则:根据以上分析,得出以下规则。

    • 最高优先级: 3 。把绳子尽可能切为多个长度为 3 的片段,留下的最后一段绳子的长度可能为 0, 1 , 2 三种情况。
    • 次高优先级: 2 。若最后一段绳子长度为 2,则保留,不再拆为 1+1 。
    • 最低优先级: 1。 若最后一段绳子长度为 1;则应把最后的 3 + 1 替换为 2 + 2,因为 2 × 2 > 3 × 1。
  • 算法流程( n = 3a + b )

    • 当 n ≤ 3 时,按照贪心规则应直接保留原数字,但由于题目要求必须剪成 m > 1 段,因此必须剪出一段长度为 1 的绳子,即返回 n - 1 。
    • 当 n > 3 时,求 n 除以 3 的 整数部分 a 和 余数部分 b (即 n = 3a + b ),并分为以下三种情况:
      • 当 b = 0 时,直接返回 3^a;
      • 当 b = 1 时,要将一个 1 + 3 转换为 2 + 2 ,因此返回 3^{a-1} ×4
      • 当 b = 2 时,返回 3^a ×2。

写法一:代码

–执行用时:0 ms --内存消耗:1.9 MB

func cuttingRope(n int) int {
    if n==1||n==2{
        return 1
    }
    if n==3{
        return 2
    }
    a:=n/3//整数部分
    b:=n%3//余数部分
    if b==0{
        return int(math.Pow(3.0,float64(a)))
    }
    if b==1{
        return int(math.Pow(3.0,float64(a)-1))*4
    }
    //b==2
    return int(math.Pow(3.0,float64(a)))*2
}


写法二:代码

绳子段切分的越多,乘积越大,且3做因数比2更优。

不断剪去 长度3 并用sum累乘

把绳子切为多个长度为 3 的片段,则留下的最后一段绳子的长度可能为 0,1,2 三种情况。

循环结束的三种情况:

  n=n-3==2 

n长度剩下2,因 n > 4 跳出循环,return 乘积为sum*2。

  n=n-3==3 

长度刚好可以被剪完,因 n > 4 跳出循环,return 乘积为sum*3。

  n=n-3==4 

再剪一次的话,长度剩下1,则最后一段绳子长度为 1;
需要把最后的 3 和 1 替换为 2 和 2,因为 2 * 2 > 3 * 1;
因 n > 4 跳出循环,return 乘积 sum*4 即可。

–执行用时:0 ms --内存消耗:1.9 MB

func cuttingRope(n int) int {
    if n==1||n==2{
        return 1
    }
    if n==3{
        return 2
    }
    sum:=1
    for n>4{
        sum*=3
        n-=3
    }
    return sum*n
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值