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

剑指offer13_剪绳子

剪绳子


给你一根长度为 n 绳子,请把绳子剪成 m 段(m、n都是整数,2≤n≤58 并且 m≥2)。

每段的绳子的长度记为 k[1]、k[2]、……、k[m]。

k[1]k[2]…k[m] 可能的最大乘积是多少?

例如当绳子的长度是 8 时,我们把它剪成长度分别为 2、3、3 的三段,此时得到最大的乘积 18。

样例
输入:8输出:18

整数拆分最大乘积问题(数学归纳与证明)

问题描述

给定正整数 N ≥ 2 N \geq 2 N2,将其拆分为若干正整数的和:
N=n1​+n2​+⋯+n**k​(k≥2)
求最大化乘积 P = n 1 × n 2 × ⋯ × n k P = n_1 \times n_2 \times \cdots \times n_k P=n1×n2××nk

数学证明

引理1:拆分中不含1

若存在 n i = 1 n_i = 1 ni=1,设剩余部分和为 S S S,则乘积 P = 1 × S = S P = 1 \times S = S P=1×S=S
S = N − 1 S = N-1 S=N1,而直接拆分 N = ( N − 1 ) + 1 N = (N-1) + 1 N=(N1)+1 的乘积为 N − 1 < N N-1 < N N1<N
矛盾!故拆分中不含1

引理2:拆分中不含≥5的数

若存在 n i ≥ 5 n_i \geq 5 ni5,将其拆分为 3 + ( n i − 3 ) 3 + (n_i-3) 3+(ni3)
3×(ni−3)=3ni−9>ni(∵ni≥5⇒2ni>9)
新拆分乘积更大,矛盾!故拆分中不含≥5的数

引理3:拆分中不含4

若存在 n i = 4 n_i = 4 ni=4,可拆分为 2 + 2 2 + 2 2+2
2×2=4=ni​
乘积不变但增加拆分项数,为后续优化创造条件

引理4:至多两个2

若有三个2( 2 × 2 × 2 = 8 2 \times 2 \times 2 = 8 2×2×2=8),替换为两个3:
3×3=9>8
乘积更大,故拆分中至多两个2

定理:最优解结构

由引理1-4,最优拆分仅含 23,且满足:

  1. 3 3 3 的数量尽可能多
  2. 2 2 2 的数量为 0, 1, 2
  3. 当余数为1时,需将一组 3 + 1 3+1 3+1 替换为 2 + 2 2+2 2+2

构造性证明

N = 3 k + r N = 3k + r N=3k+r,其中 r = N m o d 3 ∈ 0 , 1 , 2 r = N \mod 3 \in {0,1,2} r=Nmod30,1,2

r r r拆分方案最大乘积
0 k k k 3 3 3 3 k 3^k 3k
1 ( k − 1 ) (k-1) (k1) 3 3 3 + 2 2 2 2 2 2 3 k − 1 × 4 3^{k-1} \times 4 3k1×4
2 k k k 3 3 3 + 1 1 1 2 2 2 3 k × 2 3^k \times 2 3k×2

特殊边界处理

  • N = 2 N=2 N=2:强制拆分为 1 + 1 1+1 1+1(乘积1)
  • N = 3 N=3 N=3:强制拆分为 1 + 2 1+2 1+2(乘积2)

时间复杂度分析

  1. 计算 k = ⌊ N / 3 ⌋ k = \lfloor N/3 \rfloor k=N/3 O ( 1 ) O(1) O(1)
  2. 计算余数 r = N m o d 3 r = N \mod 3 r=Nmod3 O ( 1 ) O(1) O(1)
  3. 乘积计算:
    • 直接公式计算: O ( 1 ) O(1) O(1)
    • 若模拟拆分过程: O ( k ) = O ( N / 3 ) = O ( N ) O(k) = O(N/3) = O(N) O(k)=O(N/3)=O(N)

数学解释

为什么是3?

函数 f ( x ) = ( N / x ) x f(x) = (N/x)^x f(x)=(N/x)x 的极大值点在 x = N / e x = N/e x=N/e 附近
∵ e ≈ 2.718 ⇒ \because e \approx 2.718 \Rightarrow e2.718 最接近整数为3

数值验证

N N N最优拆分乘积公式计算
2 1 + 1 1+1 1+111
3 1 + 2 1+2 1+222
4 2 + 2 2+2 2+244
5 2 + 3 2+3 2+366
6 3 + 3 3+3 3+399
7 3 + 2 + 2 3+2+2 3+2+21212
8 3 + 3 + 2 3+3+2 3+3+21818
9 3 + 3 + 3 3+3+3 3+3+32727
10 3 + 3 + 2 + 2 3+3+2+2 3+3+2+23636

扩展思考

  1. 连续实数拆分:当拆分数 k → ∞ k \to \infty k,乘积收敛于 e N / e e^{N/e} eN/e
  2. 约束拆分:若限定 n i ≤ m n_i \leq m nim,问题转化为背包问题
  3. 几何解释:在 ∑ n i = N \sum n_i = N ni=N 约束下求 ∏ n i \prod n_i ni 极大值,最优解位于均值附近

题解

class Solution {
public:int maxProductAfterCutting(int n) {if(n <= 3) return 1 * (n - 1);int res = 1;if(n % 3 == 1) res = 4, n -= 4;if(n % 3 == 2) res = 2, n -= 2;while(n) res *= 3, n -= 3;return res;}
};
http://www.xdnf.cn/news/10653.html

相关文章:

  • 头歌数据库课程实验(角色管理)
  • 球展世界,筑梦中原,2025郑州台球展会,年中招商即将开启
  • 《汇编语言》第13章 int指令
  • Linux系统隐藏鼠标指针
  • 使用西门子博图V16时遇到了搜索功能报错的问题,提示缺少SIMATIC Visualization Architect组件怎么办,全网首发
  • 算法学习--持续更新
  • C++11 智能指针:从原理到实现
  • 为什么有的编程语言允许字符串和整数相加?字符串和整数比较?字符串拼接?格式串详解?字面量?
  • leetcode刷题日记——二叉树的层平均值
  • python库 PyYAML 详细使用
  • day62—DFS—太平洋大西洋水流问题(LeetCode-417)
  • 2024年12月 C/C++(三级)真题解析#中国电子学会#全国青少年软件编程等级考试
  • vue3路由跳转的三种方式
  • 利用多进程定时播放,关闭音乐播放器
  • go环境配置
  • 深入剖析C#构造函数执行:基类调用、初始化顺序与访问控制
  • UNION 与 UNION ALL 的区别
  • DAY 36 超大力王爱学Python
  • 设计模式——外观设计模式(结构型)
  • 力扣上C语言编程题
  • LangGraph(八)——LangGraph运行时
  • K3s简介、实战、问题记录
  • STM32F407寄存器操作(ADC非连续扫描模式)
  • 操作系统学习(九)——存储系统
  • AI 代理框架:使用正确的工具构建更智能的系统
  • 2025.6.1总结
  • 仓颉鸿蒙开发:制作底部标签栏
  • python训练营打卡第41天
  • 启动你的RocketMQ之旅(七)-Store存储原理
  • MySQL优化全链路实践:从慢查询治理到架构升级