[leetCode]剑指 Offer 14- I. 剪绳子
动态规化
使用动态规化的问题有一下特点:
- 目标是求解问题的最优解
- 整体问题的最优解依赖各个子问题的最优解
- 把大问题分解为小问题,各个小问题之间存在重叠部分
- 从上往下分析问题,从下往上求解问题
设
f
(
n
)
f(n)
f(n)为把长度为n
的绳子剪成若干段后乘积的最大值,则第一次剪的时候优n-1中选择,一段绳子的长度可能为1,2,3…n-1,因此
f
(
n
)
=
m
a
x
(
f
(
i
)
∗
f
(
n
−
1
)
)
f(n) = max(f(i)*f(n-1))
f(n)=max(f(i)∗f(n−1))。可以从下至上求解该问题,
f
(
2
)
=
1
,
f
(
3
)
=
2
f(2) = 1, f(3)=2
f(2)=1,f(3)=2,代码如下:
class Solution {
public int cuttingRope(int n) {
if(n < 2) return 0;
if(n == 2) return 1;
if(n == 3) return 2;
int[] products = new int[n+1];
products[0] = 0;
products[1] = 1;
products[2] = 2;
products[3] = 3;
//products[i]表示把长度为i的绳子剪成若干段后乘积的最大值
int max = 0;
for(int i = 4; i <= n; i++){
for(int j = 1; j <= i/2; j++){
int product = products[j] * products[i-j];
if(product > max){
max = product;
}
products[i] = max;
}
}
return max;
}
}
贪婪算法
使用贪婪算法解决问题时,每一步做一个贪婪的选择,基于这个选择达到最优解。
这题思路是:当n>=5时尽可能多的剪长度为3的绳子,当剩下绳子长度为4时剪成两段长度为2的绳子。
class Solution {
public int cuttingRope(int n) {
if(n < 2) return 0;
if(n == 2) return 1;
if(n == 3) return 2;
//尽可能减去长度为3的绳子段
int timesOf3 = n/3;
//最后一段绳子长度为4时不能减去3
if(n - timesOf3 * 3 == 1){
timesOf3 -= 1;
}
//减长度为4的绳子
int timesOf2 = (n - timesOf3 * 3)/2;
return (int)(Math.pow(3,timesOf3) * Math.pow(2,timesOf2));
}
}