给你一根长度为 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. 方法一:找规律

转载自





from math import powclass SolutionRegular:def cuttingRope(self, n: int) -> int:if n <= 3:return n - 1result = divmod(n, 3)if result[1] == 0:return int(pow(3, result[0]))elif result[1] == 2:return int(pow(3, result[0]) * 2)else:return int(pow(3, (result[0]-1))) << 2if __name__ == '__main__':solution = SolutionRegular()result = solution.cuttingRope(10)print(result)"""
运行结果:
36Process finished with exit code 0
"""

2. 方法二:暴力递归

转载自

从上图看出我们可以把求解 F(n) 的问题分解成求解 F(n−1) 的问题,以此类推,直到求解到 F(2) 时,F(2) = 1,递推回去,问题就得到了解决。这用到的就是分治的思想。

分治思想的解决方法往往是递归,注意到我们每次将一段绳子剪成两段时,剩下的部分可以继续剪,也可以不剪, 因此我们得到了递归函数F(n)=max(i×(n−i),i×F(n−i)),i=1,2,…,n−2。

class SolutionViolenc:def cuttingRope(self, n: int) -> int:if n == 2:return 1res = -1for i in range(1, n):res = max(res, i * max(self.cuttingRope(n - i), (n - i)))return resif __name__ == '__main__':solution = SolutionViolenc()result = solution.cuttingRope(10)print(result)"""
运行结果:
36Process finished with exit code 0
"""

复杂度分析

  • 时间复杂度:O(2^N) 。
  • 空间复杂度:O(2^N)。

3. 方法三:记忆化技术(自顶向下)

转载自

上述暴力解法会超时,但是很多进阶解法往往是暴力解法的优化。注意到上述代码中超时的原因主要是因为重复计算了 F(n),为了避免重复计算可以使用 记忆化(memoization) 技术(维基百科)。

记忆化技术的代码中经常需要建立函数 memoize 辅助实现。我们使用数组 f 来保存长度为 i时的最大长度 f[i],最后返回 f[n]即可。

from collections import dequeclass SolutionMemo:def cuttingRope(self, n: int) -> int:# 使用辅助函数def memoize(n):if n == 2:return 1if f[n] != 0:  # 如果f[n]已经计算过,直接返回避免重复计算return f[n]res = -1for i in range(1, n):res = max(res, i * max((n - i), memoize(n - i)))f[n] = resreturn resf = deque([0]*(n+1))return memoize(n)if __name__ == '__main__':solution = SolutionMemo()result = solution.cuttingRope(10)print(result)"""
运行结果:
36Process finished with exit code 0
"""

复杂度分析

  • 时间复杂度:O(2^N)。
  • 空间复杂度:O(N)。使用了数组 f。

记忆化搜索也叫“备忘录法”,它从类似上边树形图结构中的 F(n) 出发,逐步递归到已知值 F(2),可以理解成为自顶向上的解决办法。

4. 方法四:动态规划(自底向上)

转载自

使用动态规划,从已知值 F(2)逐步迭代到目标值 F(n),它是一种自底向上的方法。

from collections import dequeclass SolutionDp:def cuttingRope(self, n: int) -> int:dp = deque([0]*(n+1))dp[1] = 1dp[2] = 1for i in range(3, n+1):for j in range(i):dp[i] = max(dp[i], j*max(dp[i-j], i-j))return dp[n]if __name__ == '__main__':solution = SolutionDp()result = solution.cuttingRope(10)print(result)"""
运行结果:
36Process finished with exit code 0
"""

复杂度分析:

  • 时间复杂度:O(N^2)。
  • 空间复杂度:O(N)。

5. 方法五:动态规划优化解法

转载自

任何大于 3 的数都可以拆分为数字 1,2,3的和,且它们对 3 的余数总是0,1,2,因此我们可以仅用 dp[0],dp[1],dp[2] 表示所有大于 3 的值,这样空间复杂度可降到 O(1)。

from collections import dequeclass SolutionDpOpt:def cuttingRope(self, n: int) -> int:dp = deque([0, 1, 1])for i in range(3, n+1):dp[i % 3] = max(max(dp[(i-1) % 3], i - 1),2 * max(dp[(i-2) % 3], i - 2),3 * max(dp[(i-3) % 3], i - 3))return dp[n % 3]if __name__ == '__main__':solution = SolutionDpOpt()result = solution.cuttingRope(10)print(result)"""
运行结果:
36Process finished with exit code 0
"""

复杂度分析:

  • 时间复杂度:O(N)。
  • 空间复杂度:O(1)。使用了有限长的数组。

python--剑指offer--14- I. 剪绳子相关推荐

  1. 【LeetCode】【剑指offer】【剪绳子(二)】

    剑指 Offer 14- II. 剪绳子 II 给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m.n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]... ...

  2. 【LeetCode】剑指 Offer 14. 剪绳子

    [LeetCode]剑指 Offer 14. 剪绳子 文章目录 [LeetCode]剑指 Offer 14. 剪绳子 两道题目的区别在于第二题 n 的取值范围更大 package offer;publ ...

  3. LEETCODE | PYTHON | 剑指 Offer 58 - Ⅱ | 左旋转字符串

    LEETCODE | PYTHON | 剑指 Offer 58 - Ⅱ | 左旋转字符串 1. 题目 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部.请定义一个函数实现字符串左旋转操作 ...

  4. python连续质数计算_GitHub - xxqfft/AlgorithmsByPython: 算法/数据结构/Python/剑指offer/机器学习/leetcode...

    尝试用Python实现一些简单的算法和数据结构 之前的算法和数据结构基本都是用Swift写的,现在尝试用Python实现一些简单的算法和数据结构. update 20160704 准备加入<剑指 ...

  5. python 剑指offer 学习之路(二)

    剑指offer 学习之路 合并两个排序的链表 树的子结构 顺时针打印矩阵 包含min函数的栈 从上往下打印二叉树 二叉搜索树的后序遍历序列 二叉树中和为某一值的路径 复杂链表的复制 数组中出现次数超过 ...

  6. 剑指Offer #14 链表中倒数第k个结点(快慢指针) | 图文详解

    题目来源:牛客网-剑指Offer专题 题目地址:链表中倒数第k个结点 题目描述 输入一个链表,输出该链表中倒数第k个结点. 节点结构如下: public class ListNode {int val ...

  7. 剑指 Offer 14.剪绳子(动态规划、数学分析)

    一.题目内容 二.题目分析 这道题目讲道理,我看到的第一眼就是动态规划,但是后来提交之后,发现还有大佬考虑用数学分析得出精简解法,在这里我也会一 一阐述. 对于动态规划而言,按照老套路,首先定义dp数 ...

  8. 【LeetCode笔记】剑指 Offer 14. 剪绳子 I II(Java、动态规划、偏数学)

    文章目录 剪绳子 I 题目描述 思路 && 代码 1. 动态规划 O(n2n^2n2).O(n) 2. 最优解:数学方法 O(n).O(1) 二刷 剪绳子 II 题目描述 思路 &am ...

  9. python剑指offer剪绳子

    题目 给你一根长度为n的绳子,请把绳子剪成m段 (m和n都是整数,n>1并且m>1)每段绳子的长度记为k[0],k[1],-,k[m].请问k[0]k[1]-*k[m]可能的最大乘积是多少 ...

  10. python剑指offer替换空格_02_替换空格【python】

    1.题目描述 请实现一个函数,将一个字符串中的每个空格替换成"%20".例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 2.思 ...

最新文章

  1. 数据库性能分析及调整一例
  2. git push时提示:更新被拒绝,因为您当前分支的最新提交落后于其对应的远程分支
  3. 【java】基于JWT的token身份认证方案
  4. 如何解决服装面料纬斜问题
  5. python控制浏览器模拟鼠标点击网页标题_如何使用python来模拟鼠标点击(将经过实例自动化模拟在360浏览器中自动搜索python)...
  6. Recommended Browsers for Oracle E-Business Suite 11i/R12
  7. 解决(Missing artifact com.oracle:ojdbc14:jar:11.2.0.4.0)
  8. 先进软件开发技术与工具
  9. 6.2 数据通路的建立
  10. 深度内幕丨揭秘积分墙新颖反作弊
  11. 在word上方添加页眉和页码,单双页不同(单页页码在右,页眉在左,偶页相反)
  12. SMSBMS超市订单管理系统详解(一:准备工作)
  13. filter()“筛选”函数
  14. The7主题使用心得交流
  15. CentOS怎样添加字体
  16. 想哭的鱼最新QQ伤感日志发布:你不该,不相信我
  17. 按自己的需要获取对象中的属性
  18. 红外遥控智能小车 源码
  19. 传感器采集数据 Python123
  20. 前端实现打电话、发短信邮件

热门文章

  1. 设置Windows本地DNS域名解析hosts
  2. 如何在Win10中隐藏一个磁盘盘符
  3. Java 监控方案_Java 服务端监控方案
  4. PHP+MySql注册登陆页面开发完整代码
  5. java之打印日历表
  6. 二叉树前序遍历Java
  7. 分析智联招聘的API接口,进行数据爬取
  8. Unix编程常见问题解答(精华)
  9. 提升方法(Boosting)
  10. P014魔改8G显存