题目描述
给你一根长度为 n n n 的绳子,请把绳子剪成整数长度的 m m m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k [ 0 ] , k [ 1 ] . . . k [ m − 1 ] k[0],k[1]...k[m-1] k[0],k[1]...k[m−1] 。请问 k [ 0 ] ∗ k [ 1 ] ∗ . . . ∗ k [ m − 1 ] k[0]*k[1]*...*k[m-1] k[0]∗k[1]∗...∗k[m−1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
解法
设将长度为 n 的绳子切为 a 段:
n
=
n
1
+
n
2
+
.
.
.
+
n
a
n=n_1+n_2+...+n_a
n=n1+n2+...+na
本题等价于求解:
m
a
x
(
n
1
×
n
2
×
.
.
.
×
n
a
)
max(n_1\times n_2\times ... \times n_a)
max(n1×n2×...×na)
数学推导:
以下公式为“算术几何均值不等式” ,等号当且仅当
n
1
=
n
2
=
.
.
.
=
n
a
n_1 = n_2 = ... = n_a
n1=n2=...=na 时成立。
n
=
n
1
+
n
2
+
.
.
.
+
n
a
a
≥
n
1
n
2
.
.
.
n
a
a
\frac{n=n_1+n_2+...+n_a}{a}\geq \sqrt[a]{n_1n_2...n_a}
an=n1+n2+...+na≥an1n2...na
(略)
推论一: 将绳子 以相等的长度等分为多段 ,得到的乘积最大。
推论二: 尽可能将绳子以长度
3
3
3 等分为多段时,乘积最大。
切分规则:
- 最优: 3 3 3 。把绳子尽可能切为多个长度为 3 3 3 的片段,留下的最后一段绳子的长度可能为 0 , 1 , 2 0,1,2 0,1,2 三种情况。
- 次优: 2 2 2 。若最后一段绳子长度为 2 2 2 ;则保留,不再拆为 1 + 1 1+1 1+1 。
- 最差: 1 1 1 。若最后一段绳子长度为 1 1 1 ;则应把一份 3 + 1 3 + 1 3+1 替换为 2 + 2 2 + 2 2+2,因为 2 × 2 > 3 × 1 2 \times 2 > 3 \times 1 2×2>3×1 。
算法流程:
- 当 n ≤ 3 n \leq 3 n≤3 时,按照规则应不切分,但由于题目要求必须剪成 m > 1 m>1 m>1 段,因此必须剪出一段长度为 1 1 1 的绳子,即返回 n − 1 n - 1 n−1 。
- 当
n
>
3
n>3
n>3 时,求
n
n
n 除以
3
3
3 的 整数部分
a
a
a 和 余数部分
b
b
b (即
n
=
3
a
+
b
n = 3a + b
n=3a+b),并分为以下三种情况:
- 当 b = 0 b = 0 b=0 时,直接返回 3 a 3^a 3a ;
- 当 b = 1 b = 1 b=1 时,要将一个 1 + 3 1 + 3 1+3 转换为 2 + 2 2+2 2+2,因此返回 3 a − 1 × 4 3^{a-1} \times 4 3a−1×4;
- 当 b = 2 b = 2 b=2 时,返回 3 a × 2 3^a \times 2 3a×2。
复杂度分析
时间复杂度 O ( 1 ) O(1) O(1) : 仅有求整、求余、次方运算。
- 求整和求余运算:资料提到不超过机器数的整数可以看作是 O ( 1 ) O(1) O(1) ;
- 幂运算:查阅资料,提到浮点取幂为 O ( 1 ) O(1) O(1) 。
空间复杂度 O ( 1 ) O(1) O(1) : 变量 a a a 和 b b b 使用常数大小额外空间。
C++代码实现
class Solution {
public:
int cuttingRope(int n) {
if(n <= 3) return n - 1;
int a = n / 3, b = n % 3;
if(b == 0) return (int)pow(3, a);
if(b == 1) return (int)pow(3, a - 1) * 4;
return (int)pow(3, a) * 2;
}
};
贪心解法
力扣大佬说适合于时间有限情况下快速解题
思路:
设一绳子长度为
n
n
n
(
n
>
1
)
( n>1)
(n>1),则其必可被切分为两段
n
=
n
1
+
n
2
n=n_1+n_2
n=n1+n2 。
根据经验推测,切分的两数字乘积往往比原数字更大,即往往有
n
1
×
n
2
>
n
1
+
n
2
=
n
n_1 \times n_2 > n_1 + n_2 = n
n1×n2>n1+n2=n 。
- 例如绳子长度为 6 6 6 : 6 = 3 + 3 < 3 × 3 = 9 6 = 3 + 3 < 3 \times 3 = 9 6=3+3<3×3=9 ;
- 也有少数反例,例如 2 : 2 = 1 + 1 > 1 × 1 = 1 2 :2 = 1 + 1 > 1 \times 1 = 1 2:2=1+1>1×1=1 。
推论一: 合理的切分方案可以带来更大的乘积。
设一绳子长度为
n
(
n
>
1
)
n ( n>1 )
n(n>1),切分为两段
n
=
n
1
+
n
2
n=n_1+n_2
n=n1+n2 ,切分为三段
n
=
n
1
+
n
2
+
n
3
n=n_1+n_2+n_3
n=n1+n2+n3 。
根据经验推测,三段 的乘积往往更大,即往往有
n
1
n
2
n
3
>
n
1
n
2
n_1 n_2 n_3 > n_1 n_2
n1n2n3>n1n2 。
- 例如绳子长度为 9 9 9 : 两段 9 = 4 + 5 9=4+5 9=4+5 和 三段 9 = 3 + 3 + 3 9=3+3+3 9=3+3+3,则有 4 × 5 < 3 × 3 × 3 4 \times 5 < 3 \times 3 \times 3 4×5<3×3×3 。
- 也有少数反例,例如 6 6 6 : 两段 6 = 3 + 3 6=3+3 6=3+3 和 三段 6 = 2 + 2 + 2 6=2+2+2 6=2+2+2,则有 3 × 3 > 2 × 2 × 2 3 \times 3 > 2 \times 2 \times 2 3×3>2×2×2 。
推论二: 若切分方案合理,绳子段切分的越多,乘积越大。
总体上看,貌似长绳子切分为越多段乘积越大,但其实到某个长度分界点后,乘积到达最大值,就不应再切分了。
问题转化: 是否有优先级最高的长度
x
x
x 存在?若有,则应该尽可能把绳子以
x
x
x 长度切为多段,以获取最大乘积。
推论三: 为使乘积最大,只有长度为
2
2
2 和
3
3
3 的绳子不应再切分,且
3
3
3 比
2
2
2 更优 (详情见下表)。