剑指 Offer 14- I. 剪绳子

剑指 Offer 14- I. 剪绳子

难度中等568

给你一根长度为 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

题解:

类似这种求最优解、最大值、最小值、最短路径等的题目通常的情况下都是动态分配和贪心算法,关于动态分配,最主要的就是求出状态转移方程,而求出状态转移方程,首先就要明确对dp数组的定义。

在这道题目中,剪绳子,最少剪一次,因此m最小等于2,此时最大乘积就是(假设减去了i)i*(n-i),也就是说此时的绳子被分为两段,长度分别为i和n-i,对于剪下来的i和n-i,可以选择再次剪开或者不剪。这里就是我们的分歧点,不剪就保留原样,如果选择再次去剪

那么,假设长度为n的绳子被剪成若干段后,各段长度的最大乘积为f(n),选择剪的位置有很多,1、2、3...n-1(不能是n,否则意思就是剪到n,也就是这个绳子的长度,也就是没剪),此时的状态转移方程就是f(n)=max{f(i)*f(n-1)}(有点像一个递归),从上往下递归时可能会有很多重复计算,因此采用从下往上计算的方式,(本质也是循环求最大值),先计算f(2),f(3),后面的就方便依次计算了。f(2)=1*1=1,f(3)=1*2=2。

const n = 10;
var cuttingRope = function (n) {
  let dp = new Array(n + 1).fill(0),
    max;
  dp[2] = 1;
  for (let i = 2; i <= n; i++) {
    //拆出来是0或者1都没有意义,所以从2开始
    for (let j = 1; j < i; j++) {
      max = Math.max(j * (i - j), dp[i - j] * j); //对比找到所得值最大的方法,dp[i-j]*j是一个递归运算,能够逐个计算出每种可能性,找到最大值
      dp[i] = Math.max(dp[i], max); //dp[i]一直都是0,其实也就是把max赋给dp[i],循环给其赋值,最后得出的dp[n]就是要求得的最大值
    }
  }
  return dp[n];
};
cuttingRope(n);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值