每日刷题第18天 2021.1.13
剪绳子
- 难度:中等
- 方法:递归
题目
- 给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m-1] 。请问 k[0]k[1]...*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
示例
- 示例1
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
- 示例2
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
提示
2 <= n <= 58
解法
- 递归解法:一个数,例如
8
,罗列其情况1 7
2 6
3 5
4 4
5 3
6 2
7 1
- 总结:
- 一个数分成m段乘积的最大值,只需要计算8 / 2一半即可,因为后续会重复。
- 当前面的数固定的时候,后面数的最大值*前面的数,就是当前n的乘积的最大值。(举例如下)
- 1固定 * f(7) = f(8)
- 2固定 * f(6) = f(8)
- ......
- 上述的情况考虑完,发现遗漏一种情况:当前的两个数的最大值。例:1 * 7 、2 * 6
- 优化:第一次递归写完之后,t掉了(运行超时)。将每次已经获取到最大值的数据进行存储,优化递归做法,再次提交过了(AC)
/**
* @param {number} n
* @return {number}
*/
var cuttingRope = function(n) {
// 找到一半即可,剩下的就会重复f(2) = 1,f(3) = 2,f(4) = 4,f(5) = 6,f(6) = 9
// 递归
// 创建一个新的数组,优化递归
let record = [];
function chengJi(n) {
if(n == 2) {
return 1;
}
if (n == 3) {
return 2;
}
// 如果存在,直接输出
if (record[n]) {
return record[n];
}
let tempt = parseInt(n / 2);
let maxAns = 0;
// console.log('tempt',tempt);
for(let i = 1; i <= tempt; i++){
// 遍历组合
// console.log('i',i,'n - i',n - i);
maxAns = Math.max(i * (n - i), i * chengJi(n - i),maxAns);
// console.log('ans',maxAns);
}
record[n] = maxAns;
return maxAns;
}
return chengJi(n);
};
附录
- 递归思想的运用,自我完成✅赞👍