剑指 Offer 14- I. 剪绳子(递归)

101 阅读2分钟

每日刷题第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
  • 总结:
    1. 一个数分成m段乘积的最大值,只需要计算8 / 2一半即可,因为后续会重复。
    2. 当前面的数固定的时候,后面数的最大值*前面的数,就是当前n的乘积的最大值。(举例如下)
    • 1固定 * f(7) = f(8)
    • 2固定 * f(6) = f(8)
    • ......
    1. 上述的情况考虑完,发现遗漏一种情况:当前的两个数的最大值。例:1 * 7 、2 * 6
    2. 优化:第一次递归写完之后,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);
};

附录

  • 递归思想的运用,自我完成✅赞👍