CS-Notes/notes/14. 剪绳子.md
2020-11-05 02:09:40 +08:00

75 lines
2.3 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 14. 剪绳子
## 题目链接
[Leetcode](https://leetcode.com/problems/integer-break/description/)
## 题目描述
把一根绳子剪成多段并且使得每段的长度乘积最大
```html
n = 2
return 1 (2 = 1 + 1)
n = 10
return 36 (10 = 3 + 3 + 4)
```
## 解题思路
### 贪心
尽可能得多剪长度为 3 的绳子并且不允许有长度为 1 的绳子出现如果出现了就从已经切好长度为 3 的绳子中拿出一段与长度为 1 的绳子重新组合把它们切成两段长度为 2 的绳子以下为证明过程
将绳子拆成 1 n-1 1(n-1)-n=-1<0即拆开后的乘积一定更小所以不能出现长度为 1 的绳子
将绳子拆成 2 n-2 2(n-2)-n = n-4 n>=4 时这样拆开能得到的乘积会比不拆更大
将绳子拆成 3 n-3 3(n-3)-n = 2n-9 n>=5 时效果更好
将绳子拆成 4 n-4因为 4=2\*2因此效果和拆成 2 一样
将绳子拆成 5 n-5因为 5=2+3 5<2\*3所以不能出现 5 的绳子而是尽可能拆成 2 3
将绳子拆成 6 n-6因为 6=3+3 6<3\*3所以不能出现 6 的绳子而是拆成 3 3这里 6 同样可以拆成 6=2+2+2但是 3(n - 3) - 2(n - 2) = n - 5 >= 0 n>=5 的情况下将绳子拆成 3 比拆成 2 效果更好
继续拆成更大的绳子可以发现都比拆成 2 3 的效果更差因此我们只考虑将绳子拆成 2 3并且优先拆成 3当拆到绳子长度 n 等于 4 也就是出现 3+1此时只能拆成 2+2
```java
public int integerBreak(int n) {
if (n < 2)
return 0;
if (n == 2)
return 1;
if (n == 3)
return 2;
int timesOf3 = n / 3;
if (n - timesOf3 * 3 == 1)
timesOf3--;
int timesOf2 = (n - timesOf3 * 3) / 2;
return (int) (Math.pow(3, timesOf3)) * (int) (Math.pow(2, timesOf2));
}
```
### 动态规划
```java
public int integerBreak(int n) {
int[] dp = new int[n + 1];
dp[1] = 1;
for (int i = 2; i <= n; i++)
for (int j = 1; j < i; j++)
dp[i] = Math.max(dp[i], Math.max(j * (i - j), dp[j] * (i - j)));
return dp[n];
}
```
<div align="center"><img width="320px" src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/githubio/公众号二维码-2.png"></img></div>