剪绳子
给你一根长度为 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:
提示:
2 <= n <= 58
题解思路:
1|0方法一:暴力递归
我们往往会在头脑中形成一种很直观的暴力解法,就是列举出所有的情况,找到乘积最大的那个解。
设 F(n) 为长度为 n 的绳子可以得到的最大乘积,对于每一个 F(n),可以得到如下分解:
从上图看出我们可以把求解 F(n)的问题分解成求解 F(n−1)的问题,以此类推,直到求解到 F(2) 时,1F(2)=1,递推回去,问题就得到了解决。这用到的就是分治的思想。
分治思想的解决方法往往是递归,注意到我们每次将一段绳子剪成两段时,剩下的部分可以继续剪,也可以不剪, 因此我们得到了递归函数 F(n)=max(i×(n−i),i×F(n−i)),i=1,2,...,n−22F(n)=max(i×(n−i),i×F(n−i)),i=1,2,...,n−2。
1|1代码(超时)
- python
- Java
1|2
2|0方法二:记忆化技术(自顶向下)
上述暴力解法会超时,但是很多进阶解法往往是暴力解法的优化。注意到上述代码中超时的原因主要是因为重复计算了 F(n),为了避免重复计算可以使用 记忆化(memoization) 技术(维基百科)。
记忆化技术的代码中经常需要建立函数 memoize
辅助实现。我们使用数组 f
来保存长度为 i
时的最大长度 f[i]
,最后返回 f[n]
即可。
2|1代码
- python
- java
2|2
3|0方法三:动态规划(自底向上)
同样地,我们也可以使用动态规划,从已知值 F(2)逐步迭代到目标值 F(n),它是一种自底向上的方法。
3|1算法
建立一维动态数组 dp
:
- 边界条件:
dp[1] = dp[2] = 1
,表示长度为2
的绳子最大乘积为1
; - 状态转移方程:
dp[i] = max(dp[i], max((i - j) * j, j * dp[i - j]))
,可以这样理解:
3|2代码
- python
- java
3|3
4|0
链接:https://leetcode-cn.com/problems/jian-sheng-zi-lcof
__EOF__

本文链接:https://www.cnblogs.com/treasury/p/12618112.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?