当前位置: 首页 > news >正文

剑指offer-71、剪绳子(进阶版)

题⽬描述

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

由于答案过⼤,请对 998244353 取模。

思路解答

动态规划

自底向上计算最优解

public class Solution {private static final int MOD = 998244353;public int cutRope(int n) {if (n < 2) return 0;if (n == 2) return 1;if (n == 3) return 2;// dp[i]表示长度为i的绳子剪裁后的最大乘积long[] dp = new long[n + 1];// 基础情况:这些值不是乘积,而是长度本身(因为可以不剪)dp[0] = 0;dp[1] = 1;dp[2] = 2;dp[3] = 3;// 从长度为4开始计算for (int i = 4; i <= n; i++) {long max = 0;// 遍历所有可能的分割点,j <= i/2 避免重复计算for (int j = 1; j <= i / 2; j++) {// 比较各种分割方案的乘积long product = dp[j] * dp[i - j];if (product > max) {max = product;}}dp[i] = max % MOD;}return (int) dp[n];}
}
  • 时间复杂度:O(n²),外层循环n-3次,内层循环i/2次
  • 空间复杂度:O(n),需要dp数组存储中间结果

优化动态规划

在上面版本上优化状态转移方程,提高代码效率,直接比较j*(i-j)j*dp[i-j]的最大值

dp[i] = max(max(j × (i-j), j × dp[i-j])) 其中 1 ≤ j < i

  • j × (i-j):剪一刀的情况
  • j × dp[i-j]:剪多刀的情况
public class Solution {private static final int MOD = 998244353;public int cutRope(int n) {if (n < 2) return 0;if (n == 2) return 1;if (n == 3) return 2;long[] dp = new long[n + 1];dp[1] = 1;for (int i = 2; i <= n; i++) {for (int j = 1; j < i; j++) {// 三种情况取最大值:不剪、剪一刀、剪多刀long temp = Math.max(j * (i - j), j * dp[i - j]);dp[i] = Math.max(dp[i], temp);}dp[i] %= MOD;}return (int) dp[n];}
}
  • 时间复杂度:O(n²),双重循环
  • 空间复杂度:O(n),dp数组空间

贪心算法(最优解)

我们仔细观察就会发现:要想乘积⽐较⼤,在没有1的前提下,优先使⽤3,如果出现1,那么优先使⽤2

⽐如:

2 = 1 + 1
3 = 1 + 2
4 = 2 + 2
5 = 2 + 3
6 = 3 + 3
7 = 3 + 2 + 2
8 = 3 + 3 + 2
9 = 3 + 3 + 3
10 = 3 + 3 + 2 + 2
11 = 3 + 3 + 3 + 2
12 = 3 + 3 + 3 + 3
public class Solution {public long cutRope(long number) {if (number == 2) return 1;if (number == 3) return 2;long res = 1;while (number > 4) {res *= 3;res = res % 998244353;number -= 3;}return res * number % 998244353;}
}

结果很不幸:运⾏超时:您的程序未能在规定时间内运⾏结束,请检查是否循环有错或算法复杂度过⼤。

于是我们需要想到其他的⽅式,如何快速计算 3 的 n 次⽅,这是我们需要解决的问题,因为在尽量凑 3的前提下,有以下三种情况:

  • 被 3 整除 等于 n :直接计算 3 的 n 次幂
  • 被 3 取余数为1,结果等于 n :直接计算 3 的 (n-1) 次幂,再乘以4,为什么呢?因为余数是1,我们避免有1,需要借出 3,和 1凑成为 4,4 分段之后的最⼤乘积也是 4(2 * 2)
  • 被 3 取余数为 2,结果等于 n:直接计算 3 的 n 次幂 ,再乘以2

也就是说,当n≥5时,优先剪出长度为3的段;剩余4时剪成2×2

为什么选择3?

  1. 数学证明:当n ≥ 5时,3(n-3) ≥ 2(n-2) > n
  2. 接近自然底数e:最优分段长度应接近e ≈ 2.718,3是最接近的整数
  3. 4的特殊处理:2×2 > 3×1,所以剩余4时剪成2×2而不是3×1

执行过程示例(n=10):

10 ÷ 3 = 3段...剩余1
调整:2段3 → 剩余4 → 剪成2×2
结果:3² × 2² = 9 × 4 = 36

在计算幂次⽅的时候,为了避免溢出,在每次相乘的时候,都需要除以998244353 ,为了计算快,每次以⾃身相乘的⽅式计算,代码如下:

public class Solution {private static final int MOD = 998244353;public int cutRope(int n) {// 特殊情况处理if (n <= 3) return n - 1;// 计算可以剪出多少段长度为3的绳子int countOf3 = n / 3;// 处理剩余部分:当剩余长度为1时,调整策略if (n - countOf3 * 3 == 1) {countOf3--; // 减少一段3,与剩余的1组成4}// 计算剩余部分能剪出多少段长度为2的绳子int countOf2 = (n - countOf3 * 3) / 2;// 计算结果:3的countOf3次方 × 2的countOf2次方long result = pow(3, countOf3) * pow(2, countOf2);return (int) (result % MOD);}/*** 快速幂算法计算a的b次方取模*/private long pow(long a, long b) {long result = 1;while (b > 0) {if ((b & 1) == 1) {result = (result * a) % MOD;}a = (a * a) % MOD;b >>= 1;}return result;}
}
  • 时间复杂度:O(1),只有常数次操作
  • 空间复杂度:O(1),只使用固定变量
http://www.jsqmd.com/news/336216/

相关文章:

  • 营销陪跑公司哪家强?2026年营销落地陪跑公司推荐与评价,解决团队适配与集成痛点 - 品牌推荐
  • 2026年城投优质资产管理系统推荐 大型集团系统有哪些 - 品牌2025
  • <span class=“js_title_inner“>哦豁,我又成功逆向了一个sign</span>
  • 背包专题 - 古代王国寻宝问题
  • 2026年数据拉通与集成服务靠谱公司推荐汇总 - 品牌2025
  • <span class=“js_title_inner“>一个免费远程控制电脑及手机的神器</span>
  • Typora软件/markdown语法快速入门
  • <span class=“js_title_inner“>Fairy Mobile GUI Agent——RGR、OCA、EMA的综合落地</span>
  • 富马酰化如何成为代谢与表观遗传调控的新枢纽?
  • <span class=“js_title_inner“>提示词软件危机——Agentic AI系统的工程化挑战</span>
  • <span class=“js_title_inner“>15年前,小沈阳一个晚上爆红年赚上亿,如今却“销声匿迹”?</span>
  • 【Linux 进程实战】C 语言实现父子进程协作:定时日志生成 + 自动清理系统(附完整可运行代码)
  • 2026年激光测距仪制造企业综合实力排名,哪家性价比高选哪家 - 工业设备
  • AIGC 应用工程师(3-5 年)面试题精讲:从基础到实战的系统备战清单
  • <span class=“js_title_inner“>如何破解3D“创作鸿沟”?元境携手北航的这场高峰论坛将揭晓路径!</span>
  • <span class=“js_title_inner“>【观察】走进“AI数智南研”,体验智慧园区新标杆</span>
  • Linux命令-look(在已排序的文件中查找以特定字符串开头的行)
  • <span class=“js_title_inner“>LLM4SE的2025:LLM 改变了写代码的方式,但还没改变软件工程</span>
  • <span class=“js_title_inner“>欢迎申报2025数智产品用户选型年度大奖</span>
  • 202560202
  • <span class=“js_title_inner“>幂等性的劣化:从数学确定性到AI不确定性的演进</span>
  • <span class=“js_title_inner“>AI Coding评测,到底谁在“裸泳”?</span>
  • 2026年知名的装修板材/家具定制板材热门品牌厂家推荐 - 行业平台推荐
  • 基于PHP、asp.net、java、Springboot、SSM、vue3的酒店客房系统的设计与实现
  • <span class=“js_title_inner“>Agentic AI系统性工程框架——RGR、OCA与EMA三位一体方法论</span>
  • <span class=“js_title_inner“>正式裁员64796人,赔偿N+4!</span>
  • <span class=“js_title_inner“>年终总结 | AI 正在光速进化,而我们还得在 2026 年的泥潭里挣扎</span>
  • 【Linux 封神之路】进程进阶实战:fork/vfork/exec 函数族 + 作业实现(含僵尸进程解决方案)
  • <span class=“js_title_inner“>年度好物大赏 | 2025年“把钱花在了刀刃上”的幸福瞬间</span>
  • <span class=“js_title_inner“>Qwen3-Coder: 在世界中自主编程</span>