剑指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];
}
posted @ 2020-04-18 19:38  木子呆头  阅读(180)  评论(0编辑  收藏  举报