剑指offer 14- I. 剪绳子
题目描述
解题思路
dp
参考题解:动态规划、数学
此题是343. 整数拆分的变体,官方题解讲的比较清楚。
时间o(n²),空间o(n)
class Solution {
public int cuttingRope(int n) {
//定义:dp[i]表示对于长度为i的绳子,剪成至少两段后可能的最大乘积
int[] dp = new int[n + 1];
//base case
dp[1] = 1;
for (int i = 2; i <= n; i++) {
for (int j = 1; j < i; j++) {
//两种选择:每次将 i - j 剪出来后,剩下的 j 的部分选择不剪或继续剪
dp[i] = Math.max(dp[i], Math.max(j * (i - j), dp[j] * (i - j)));
}
}
return dp[n];
}
}
数学
结论:拆分出来的整数越接近e,则乘积越大。
根据 n % 3 的结果分类讨论:(设 m = n / 3)
- 若 n % 3 == 0,则拆分成 m 个3
- 若 n % 3 == 1,则拆分成 m - 1 个3和2个2
- 若 n % 3 == 2,则拆分成 m 个3和1个2
上述讨论是在 n ≥ 4 时,当 n ≤ 3 时不适用,所以需要单独讨论:
- 若 n = 2,有 2 = 1 + 1,最大乘积是1
- 若 n = 3,有 3 = 1 + 1 + 1 = 1 + 2 两种情况,最大乘积是2
因此,可以合并为最大乘积 = n - 1
时间o(1),空间o(1)
tips:对于求整和求余运算,不超过机器数的整数可以看作是 O(1);
class Solution {
public int cuttingRope(int n) {
if (n <= 3) {
return n - 1;
}
int quotient = n / 3;
int remainder = n % 3;
if (remainder == 0) {
return (int)Math.pow(3, quotient);
} else if (remainder == 1) {
return (int)Math.pow(3, quotient - 1) * 4;
} else {
return (int)Math.pow(3, quotient) * 2;
}
}
}