剑指offer - 动态规划与贪婪
减绳子
问题描述:
给你一根长度为 n 的绳子,请把绳子剪成整数长的 m 段(m、n 都是整数,n>1 并且 m>1),每段绳子的长度记为 k[0],k[1],...,k[m]。请问 k[0]xk[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是 8 时,我们把它剪成长度分别为 2、3、3 的三段,此时得到的最大乘积是 18。
输入描述: 输入一个数 n,意义见题面。(2 <= n <= 60)
输出描述: 输出答案。
输入: 8
输出: 18
方法一:数学公式法(贪婪算法)
解题思路:
绳子长度为 n,分成 m 份,
假设每份长度为 x,那么 m=n/x;
那么结果就是 f(x)=x^(n/x)
所以问题就回到了 n/3 的个数上面当 n 能被 3 整除的时候,乘积=n^(n/3)
当 n 除 3 余 1 的时候,这时候发现多了一个 1,这个 1 是不是很鸡肋,但是把前面的一个 3 拿出来,把这个一个 1 和前面一个 3 分解为 2 和 2,就变大了,所以乘积为 3^(n/3 - 1) * 4
当 n 除 3 余 2 的时候,乘积为 n^(n/3) * 2
function cutRope(number) {
// write code here
if (number <= 1) return 0;
if (number === 2) return 1;
if (number === 3) return 2;
var m = number % 3;
switch (m) {
case 0:
return Math.pow(3, number / 3);
case 1:
return Math.pow(3, parseInt(number / 3) - 1) * 4;
case 2:
return Math.pow(3, parseInt(number / 3)) * 2;
}
}
方法二:动态规划 DP
function cutRope(number) {
// write code here
if (number <= 1) return 0;
if (number === 2) return 1;
if (number === 3) return 2;
var arr = [0, 1, 2, 3];
for (let i = 4; i <= number; i++) {
var max = 0;
for (let j = 1; j <= parseInt(number / 2); j++) {
var max = 0;
max = Math.max(arr[j] * arr[i - j], max);
arr.push(max);
}
}
return arr[arr.length - 1];
}