【LeetCode】剑指14—— I. 剪绳子(难度:中等)

【LeetCode】剑指14—— I. 剪绳子(难度:中等)

题目描述

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

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

  2. 示例 2:
    输入: 10
    输出: 36
    解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36

提示:2 <= n <= 58

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/jian-sheng-zi-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

思路一:遍历最优“段数”寻找最优解

段数最少为2,最大为n/2+1(或者说n/2向上取整),在这个区间内进行遍历,如此一来,假设当前段数为m,那么每段的最小长度为n/m,此时会余下n%m的长度,将余下的长度给n%m个段多分配1个单位,然后计算乘积即可。最后选出最大乘积。

思路二:如果把数字范围扩展到全体正数,那么利用均值不等式获得的最优解其实是:

f ( m ) = ( n / m ) m f(m)=(n/m)^m f(m)=(n/m)m

其中m为段数。对m通过对数求导可以算出当 m = n / e m=n/e m=n/e 时取得最小值,此时每段的长度为 e = 2.71828... e=2.71828... e=2.71828...,自然数3是最接近的,因此尽可能地把绳子切成多个长度为3的片段,此时余数会有0、1、2三种情况

  • 若余数为0,说明切分得很正好。但此时会产生一种情况:就是n=3。由于段数必须大于等于2,所以必须拆分成1和2。
  • 若余数为1:则应该把一份3+1替换成2+2,因为2×2>3×1
  • 若余数为2:保留,不继续拆分成1+1。但此时会产生一种情况:就是n=2。由于段数必须大于等于2,所以必须拆分成1和1。

代码详解

思路一:遍历寻优

class Solution {
    public int cuttingRope(int n) {
        int ans = 1;
        for(int i = 2; i <= n/2+1; ++i) { // i为段数,遍历的最小值为2,最大值为n/2向上取整
            int temp = 1; // 累乘
            int len = n / i; // 每段最小长度
            int rest = n - i * len; // 余下的长度,需要分给某些段各1个单位长度
            for(int j = 0; j < i; ++j) {
                if(j < rest) {
                    temp *= (len+1); // rest个段数需要乘上(len+1)
                } else {
                    temp *= len; // 其余段数只需乘上len
                }
            }
            ans = Math.max(ans, temp); // 取最大值
        }
        return ans;
    }
}

思路二:数学法

class Solution {
    public int cuttingRope(int n) {
        if(n <= 3) { // 特殊情况
            return n-1;
        } else {
            return (int)Math.pow(3, n/3) * 4 / (4 - n%3);
            // (int)Math.pow(3, n/3)这块应该都懂
            // * 4 / (4 - n%3)这部分分为三种情况
            // 若n%3=0,则*4/4=1,表示不再多乘
            // 若n%3=1,则*4/3,表示把一个(3,1)(也就是除以3)替换成(2,2)(也就是乘以4)
            // 若n%3=2,则*4/2=2,保留余数2
        }
    }
}

注意点

  1. 遍历法没超时我是没想到的(做完剪绳子II之后发现,因为题目限定n很小而已,再大越long上界需要取余的时候遍历法就不能用了),这题的数学法还要用到求导我又是没想到的
  2. 友情链接:【LeetCode】剑指14—— II. 剪绳子II(难度:中等)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值