Sword Point Offer-Question 14 (Java Edition): Cut the Rope

Reference from: "Sword Pointing Offer - Famous Enterprise Interviewer Talking About Typical Programming Questions"

Question : Cut a rope
Give you a rope of length n, please cut the rope into m segments (m and n are integers, n>1 and m≥1). The length of each piece of rope is denoted as k[0], k[1], ..., k[m]. What is the largest possible product of k[0]k[1]...k[m]? For example, when the length of the rope is 8, we cut it into three sections of length 2, 3, and 3, and the maximum product 18 is obtained at this time.

Main idea :
idea 1: dynamic programming: f(n) = max(f(i)*f(ni)), where 0<i<n, traverse i from 1 to n/2, and find the largest f(n ) . To avoid double-counting, choose a bottom-to-top order calculation.

Idea 2: Greedy algorithm: When n is greater than or equal to 5, cut the rope with length 3 as much as possible, and when the remaining length is 4, cut the rope into 2 pieces of rope with length 2.
Prove: When n≥5, 2(n-2)>n, 3(n-3)>n, and 3(n-3)≥2(n-2)
When n=4, 2×2>3× 1

Key Points : Dynamic Programming, Greedy Algorithms

Time complexity : dynamic programming: O(n^2); greedy algorithm: O(1)

public class CutRope
{
    public static void main(String[] args)
    {
        int length = 8;
        int expected = 18;
        int result = maxProductAfterCutting1(length);
        System.out.println(result);
        System.out.println(maxProductAfterCutting2(length));
    }

    /**
     * 动态规划
     *
     * @param length
     * @return
     */
    private static int maxProductAfterCutting1(int length)
    {
        if (length < 2)
            return 0;
        if (length == 2)
            return 1;
        if (length == 3)
            return 2;

        int[] products = new int[length + 1];
        products[0] = 0;
        products[1] = 1;
        products[2] = 2;
        products[3] = 3;

        int max;
        for (int i = 4; i <= length; ++i)
        {
            max = 0;
            //f(n) = max(f(i)*f(n-i))   0<i<n
            for (int j = 1; j <= i / 2; ++j)
            {
                int currentProduct = products[j] * products[i - j];
                if (max < currentProduct)
                    max = currentProduct;
            }
            products[i] = max;
        }
        max = products[length];
        return max;
    }

    /**
     * 贪婪算法
     * @param length
     * @return
     */
    private static int maxProductAfterCutting2(int length)
    {
        if(length < 2)
            return 0;
        if(length == 2)
            return 1;
        if(length == 3)
            return 2;

        // 尽可能多地减去长度为3的绳子段
        int timesOf3 = length / 3;

        // 当绳子最后剩下的长度为4的时候,不能再剪去长度为3的绳子段。
        // 此时更好的方法是把绳子剪成长度为2的两段,因为2*2 > 3*1。
        if(length - timesOf3 * 3 == 1)
            timesOf3 -= 1;

        int timesOf2 = (length - timesOf3 * 3) / 2;

        return (int) (Math.pow(3, timesOf3)) * (int) (Math.pow(2, timesOf2));
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325891038&siteId=291194637