Leetcode 剑指 Offer 14- I. 剪绳子

  • 题目
  • 1、dp做法
  • 2、数学做法:算术几何均值不等式

题目

给你一根长度为 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】
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
【示例 2】
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
【提示】
2 <= n <= 58

1、dp做法

对于本题,我们可以先手算出一些规律:
2 = 1 + 1
3 = 1 + 2
4 = 1 + 3 = 2 + 2
5 = 1 + 4 = 2 + 3
6 = 1 + 5 = 2 + 4 = 3 + 3
7 = 1 + 6 = 2 + 5 = 3 + 4
8 = 1 + 7 = 2 + 6 = 3 + 5 = 4 + 4
……
对应的最大乘积
2 ---- 1 * 1 = 1
3 ---- 1 * 2 = 2
4 ---- 2 * 2 = 4
5 ---- 2 * 3 = 6
6 ---- 3 * 3 = 9
7 ---- 3 * (4)= 3 * 4 = 12
8 ---- 3 * (5)= 3 * 6 = 18
……
可以发现,因为必须剪成两段及以上,所以2 和 3 的最大乘积是 n - 1.
但是在其他大于3的数里面,遇到需要拆成 2 或者 3 去加的时候,不应该把2拆成1 + 1,把3拆成1 + 2。
比如说 6 ,拆成 3 + 3,就可以得到 3 * 3 = 9 的最大乘积,无须再拆成 6 = 1 + 2 + 1 + 2。

设 n 是绳子长度, f (n)是最大乘积,则 f (n)= f (a)+ f(b),其中 a + b = n。
但是根据常识,我们并不需要将 a 从 1 遍历到 n / 2,只需要去比较当 a = n / 2 和 a = n / 2 - 1时对应的 f (n)即可。

代码如下:

//用时0ms
class Solution {public int cuttingRope(int n) {if (n == 2) return 1;else if (n == 3) return 2;int[] book = new int[n + 3];book[1] = 1;book[2] = 2;book[3] = 3;for (int i = 4; i <= n; ++ i) {int a = i / 2;book[i] = Math.max(book[a] * book[i - a], book[a - 1] * book[i - a + 1]);}return book[n];}
}

2、数学做法:算术几何均值不等式

虽然在leetcode上,上面的dp解法是0ms,但是时间和空间复杂度都是O(n),其实可以用数学在时间和空间都是O(1)复杂度的情况下解决本问题。

这道题实际上就是在问给定一个正整数 n,将其至少拆分成两个正整数,并使得这些正整数的乘积最大。
即 n = n1 + n2 + …… + na 时,求 Max( n1 * n2 * …… * na)

在高中阶段,我们接触过不等式:

而它其实是算术—几何均值不等式(AM-GM不等式) 在 n = 2 时的一个特例:

当且仅当n1 = n2 = …… = na 时,等号成立。

那么对于本题,也就是说,当绳子被尽可能均分成 a 份时,取到的乘积是最大的。
也就是说,我们可以设分割后绳子的长度 x = n / a,那么最大乘积 f (n) = x ^ a = x ^ (n / x) = (x ^ (1/x)) ^ n。由于n是常数,所以本题就转换成了求 x ^ (1/x) 的最大值

令 y = x^(1/x) ,取对数 lny = (1/x)lnx
对x求导得到:y′/y = (-1/x²)lnx+1/x² = (1/x²)(1-lnx)
令y′ = y(1/x²)(1-lnx)=0,得1 - lnx = 0,lnx = 1
所以 x = e ≈ 2.7是极大值点,极大值y(e) = e^(1/e) ≈1.444667.

但是因为题目是要求把绳子分成整数段,所以用极大值y(e)^ n 误差比较大,根据 x = e ≈ 2.7,可以判断出最终分成长度为2或者3时,是比较好的。

且y(3)=3 ^ (1/3) ≈ 1.44 > y(2)=2 ^ 1/2 ≈ 1.41,由此可知:能分成length == 3就分成length == 3,凑不到3的部分,如果是2,就直接是2,不用再分下去;如果是1,就拿出一个3和1凑成 2 * 2,这样最终乘积会最大。(另:没办法手算出开方时,可以同时(y(2)) ^ 6 和 (y(3) ) ^ 6同样可以比较出大小)

例如对于 n = 8 ,最多只能拿出2个3,剩下一个2不用再拆了,所以8 = 2 + 3 + 3 时,乘积达到最大值;
对于 n = 9,刚刚好拆成 9 = 3 + 3 + 3,此时达到最大值;
对于 n = 10,拿出 3 个 3后,只剩下 1,因为 1 * 3 < 2 * 2,所以应该拿出一个 3 和 1凑成 2 * 2,即 10 = 3 + 3 + 2 + 2 时乘积达到最大值。

代码如下:

class Solution {public int cuttingRope(int n) {if (n < 4) return n - 1;else {int a = n / 3;int b = n % 3;if (b == 0) return (int)Math.pow(3, a);else if (b == 1) return (int)Math.pow(3, a - 1) * 4;else return (int)Math.pow(3, a) * 2;}}
}

dp / 算术几何均值不等式 求 正整数拆分后的最大乘积相关推荐

  1. 1到1亿的自然数,求所有数的拆分后的数字之和

    1到1亿的自然数,求所有数的拆分后的数字之和,如286 拆分成2.8.6,如1到11拆分后的数字之和 => 1 + ... + 9 + 1 + 0 + 1 + 1 /*** 1到1亿的自然数,求 ...

  2. 【组合数学】生成函数 ( 正整数拆分 | 重复有序拆分 | 不重复有序拆分 | 重复有序拆分方案数证明 )

    文章目录 一.重复有序拆分 二.不重复有序拆分 1.无序拆分基本模型 2.全排列 三.重复有序拆分方案数证明 参考博客 : 按照顺序看 [组合数学]生成函数 简要介绍 ( 生成函数定义 | 牛顿二项式 ...

  3. 【组合数学】生成函数 ( 正整数拆分 | 正整数拆分基本模型 | 有限制条件的无序拆分 )

    文章目录 一.正整数拆分基本模型 二.有限制条件的无序拆分 参考博客 : [组合数学]生成函数 简要介绍 ( 生成函数定义 | 牛顿二项式系数 | 常用的生成函数 | 与常数相关 | 与二项式系数相关 ...

  4. 【组合数学】生成函数 ( 正整数拆分 | 无序不重复拆分示例 )

    文章目录 一.正整数拆分总结 二.正整数拆分示例 参考博客 : [组合数学]生成函数 简要介绍 ( 生成函数定义 | 牛顿二项式系数 | 常用的生成函数 | 与常数相关 | 与二项式系数相关 | 与多 ...

  5. 【组合数学】生成函数 ( 正整数拆分 | 无序 | 有序 | 允许重复 | 不允许重复 | 无序不重复拆分 | 无序重复拆分 )

    文章目录 一.正整数拆分 二.无序拆分 1.无序拆分 不允许重复 2.无序拆分 允许重复 参考博客 : [组合数学]生成函数 简要介绍 ( 生成函数定义 | 牛顿二项式系数 | 常用的生成函数 | 与 ...

  6. NYOJ 90 —— 求正整数n划分为若干个正整数的划分个数

    整数划分 时间限制:3000 ms  |  内存限制:65535 KB 描述 将正整数n表示成一系列正整数之和:n=n1+n2+-+nk,  其中n1≥n2≥-≥nk≥1,k≥1.  正整数n的这种表 ...

  7. 正整数m的百位数字python_求正整数m的百位数字

    [多选题]关于三阀组的使用,下列说法正确的是() (6.0分) [多选题]下列流量计不能用于气体测量的是() (6.0分) [填空题]执行下列Python语句将产生的结果是 . m=True n=Fa ...

  8. java1到n所有质数_实验一:实现求正整数1-N之间所有质数的功能,并进行测试。...

    实验一 Java开发环境的熟悉(Linux + Eclipse) 实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用Eclipse 编辑.编译.运行.调试Java程序. 命令行下的程序开 ...

  9. C++——算术表达式的求值(数据结构课程设计)

    数据结构课程设计--算术表达式的求值 1.实验目的 1.在课程设计中提高学生的动手能力和编程能力; 2.在课程设计中提高数据结构中理论知识(栈和二叉树等知识)的应用. 3.在课程设计中提高自己对各个方 ...

最新文章

  1. 十种经典排序算法精粹(c语言版本)
  2. 推荐10个小众简约,但是实用的软件和网站
  3. 【人工智能】人类该如何看待人工智能的“诗与远方”?
  4. c语言中二进制文件的访问速度比文本文件快,以下叙述中错误的是( )。A.C语言中对二进制文件的访问速度比文本文件快B...._考试资料网...
  5. python正则表达式--分组、后向引用、前(后)向断言
  6. 惊呆!学习MySQL真的这一篇就够了!太全了
  7. 【SpringBoot零基础案例03】【IEDA 2021.1】SpringBoot框架核心配置文件application.properties的使用
  8. linux打开pythonshall,linux系统shell脚本后台运行python程序
  9. 基于HAProxy+Keepalived高可用负载均衡web服务的搭建
  10. 关于地图制图大赛的8点说明,附地图学习资源
  11. 点歌台 PHP,MeMusic3.0 PHP在线点歌系统 - 下载 - 搜珍网
  12. python的标准库学习之__buitin__
  13. 按平均成绩排行c语言文件操作,学生成绩管理系统(c语言结构体以及文件操作)实验报告精选.doc...
  14. 人工智能之自然语言处理技术总结与展望
  15. dell5580bios恢复出厂_戴尔笔记本如何恢复Bios出厂设置?
  16. raft2020年更新_Raft6月1日更新了什么 Raft6月1日更新内容介绍
  17. recon-ng的使用
  18. 美团综合业务推荐系统的质量模型与实践
  19. 【Unity3D 灵巧小知识点】☀️ | Unity 四元数、欧拉角 与 方向向量 之间转换
  20. DSP程序开发与优化经验之四:TMS320C64x+ DSP------Using Cache

热门文章

  1. Linux升级内核以及删除Linux多余的内核
  2. 必知必会 | 音视频基础知识
  3. 初学数据库---数据库设计学习
  4. Qt5.9.0下载与安装(windows版本)
  5. python之去掉字符串中空格的方法
  6. android横向卡片式布局,创建卡片式布局  |  Android 开发者  |  Android Developers
  7. Java的MessageDigest类、MD5算法
  8. fluter set get
  9. Python第三方模块:PyQt5简介
  10. 数据结构之散列表(七)