1. 本题知识点
贪心算法
2. 题目描述
现在有一根长度为 n 的绳子,请你把它任意剪成 m 段,请问每一段绳子长度的乘积最大值是多少?(n>1,m>1)
例如,当绳子的长度是 8 时,我们把它剪成长度分别为 2、3、3 的三段,此时得到的最大乘积是 18。
Input
绳子长度:8
Output
最大乘积:18
3. 解题思路
贪心算法
- 首先,这道题给了我们限制条件(总绳子长度为 n)。然后,它希望我们在满足限制条件的情况下,求期望值最大(每一段绳子长度的乘积最大值),我们就应该联想到贪心算法了。
- 如果满足每一段绳子的长度都是最优解(各个子问题都是局部最优解),那么每一段绳子长度的乘积就是最大值(整个问题就是最优解),那这道题就可以用贪心算法来解决。
我们先列举几种最大乘积的情况
n | 最大乘积 |
---|---|
2 | 1x1 = 1 |
3 | 2x1 = 2 |
4 | 2x2 = 4 |
5 | 3x2 = 6 |
6 | 3x3 = 9 |
7 | 3x2x2 = 12 |
8 | 3x3x2 = 18 |
9 | 3x3x3 = 27 |
10 | 3x3x2x2 = 36 |
11 | 3x3x3x2 = 54 |
12 | 3x3x3x3 = 81 |
可以发现:
-
当 n = 2,n = 3 时,只有在这两种情况下,出现了剪一段绳子的长度是 1,所以我们把它们当作特殊情况。
-
当 n > 3 时,剪一段绳子的长度要么是 2,要么是 3,并且优先是 3(因为 3x3 > 2x2x2)
-
出现长度为 2 的绳子只有两种情况:
- 前面都是长度为 3,最后一段绳子长度为 2(比如:n = 8,剪为 3x3x2)
- 假设前面都是长度为 3,最后一段绳子长度为 1,此时会拿出一个长度为 3 和长度为 1 的绳子,把它们换为两段长度为 2 的绳子。(比如:n = 7,假设剪为 3x3x1,这时就换成 3x2x2,因为 2x2>3x1)
4. 代码
public class Solution {
/**
* 输入绳子长度 target,将它剪成若干段后,返回每一段绳子长度的乘积最大值
* @param target
* @return
*/
public int cutRope(int target) {
if (target == 2) {
return 1;
} else if (target == 3) {
return 2;
} else {
// 最多能剪出长度为 3 的绳子数量
int numOfThree = target / 3;
// 最后一段绳子的长度
int LengthOfLast = target % 3;
// 当最后一段长度为 2 时
if (LengthOfLast == 2) {
return (int) (2 * Math.pow(3, numOfThree));
}
// 当最后一段长度为 1 时
else if (LengthOfLast == 1) {
return (int) (2 * 2 * Math.pow(3, numOfThree - 1));
}
// 当每一段长度都为 3 时
else {
return (int) Math.pow(3, numOfThree);
}
}
}
}