剑指offer(10)——剪绳子

157 阅读2分钟

这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战

题目 给你一根长度为 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,3,,,,

给你一根长度为n绳子,请把绳子剪成m段(m、n都是整数,n>1并且m>1)。每段的绳子的长度记为k[0]、k[1]、……、k[m]。问k[0] * k[1]*…*k[m]可能的最大乘积是多少?例如当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到最大的乘积18。

有一段长度为n的绳子,剪的第一刀可以在[1,n-1]。 第一刀下去后,绳子分成两部分,假设在i处剪断,绳子两部分就分别为:[0,i]与[i,n],那么找出第一刀最合适的位置,其实就是找i在哪下刀,可以使得[0,i]与[i,n]的乘积最大。 ————————————————

贪婪算法: 首先,当n>=5的时候,我们可以证明先2(n-2)>n。也就是说,当绳子剩下的长度大于等于5的时候,我们就把它剪成长度为3或者2的绳子段。另外,当n>5时,3(n-3)>=2(n-2),因此我们应该尽可能地多剪长度为3的绳子段。 前面证明的前提是n>=5。那么当绳子的长度为4呢?在长度为4的绳子上剪一刀,有两种可能的结果:剪成长度分别为1和3的两根绳子,或者两根长度都为2的绳子。很明显是 2 x 2 > 3 x 1。 ————————————————

代码

let cache = [0, 0, 1];  // 记忆数组,且数组不能写里面递归占内存
var cuttingRope = function (n) {
    if(cache[n]){
        return cache[n];
    }
    let max = 0;
    for (let i = 1; i < n - 1; i++) {
        let temp = Math.max(i * cuttingRope(n - i), i * (n - i));
        if (temp > max) {
            max = temp;
        }
    }
    return cache[n] = max;  // 将f(n)的结果存储起来
};