• 【Offer】[14] 【剪绳子】


    题目描述

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

    思路分析

    1. 动态规划: 定义函数f(n) 为将长度为n的绳子剪成若干段后各段长度乘积的最大值

      • f(0) = 0
      • f(1) = 0 因为此处绳子的长度大于乘积的值, 所以实际操作的时候 使用绳子的长度
      • f(2) = 1 同上
      • f(3) = 2 同上
      • f(n) = max(f(i)*f(n-i)), 1< i <n

        这样按照从下到上的顺序计算

    2. 贪心算法:尽可能多的剪长度为3的绳子段

    测试用例

    1. 功能测试(长度大于5)
    2. 边界值测试(长度1,2,3,4)

    Java代码

    public class Offer14 {
        public static void main(String[] args) {
            System.out.println("功能测试--->");
            test1();
            System.out.println("边界值测试--->");
            test2();
        }
        
        public static int maxProductAfterCutting(int n) {
            return Solution2(n);
        }
    
        /**
         * 解法一:动态规划
         * 思路: 定义函数f(n) 为将长度为n的绳子剪成若干段后各段长度乘积的最大值
         * 1.  f(0) = 0
         * 2.  f(1) = 0  因为此处绳子的长度大于乘积的值, 所以实际操作的时候 使用绳子的长度
         * 3.  f(2) = 1  同上
         * 4.  f(3) = 2  同上
         * 5.  f(n) = max(f(i)*f(n-i)), 1< i <n
         * 
         * @param n
         * @return
         */
        private static int Solution1(int length) {
            
            if(length<=1) {
                return 0;
            }
            if(length == 2 ) {
                return 1;
            }
            if(length == 3) {
                return 2;
            }
            int[] product = new int[length+1];
            product[0] = 0;
            product[1] = 1;
            product[2] = 2;
            product[3] = 3;
            
            for(int i=4 ;i<=length;i++) {
                int max = 0;
                for(int j=1;j<=i/2;j++) {
                    if(max < product[j]*product[i-j]) {
                        max = product[j] * product[i-j];
                    }
                }
                product[i] = max;
            }
            
            return product[length];
        }
        
        /**
         * 解法二: 贪心算法
         * 思路: 尽可能多的减成长度为3的绳子段
         */
        private static int Solution2(int length) {
            if(length<=1) {
                return 0;
            }
            if(length==2) {
                return 1;
            }
            if(length==3 ) {
                return 2;
            }
            
            int timeOf3 = length/3;
            if(length - timeOf3*3 == 1) {
                timeOf3 -= 1;
            }
            int timeOf2 = (length-timeOf3*3) / 2;
            return (int) Math.pow(3, timeOf3) * (int)Math.pow(2,timeOf2);
        }
        
        /**
         * 测试功能
         */
        private static void test1() {
            System.out.println("绳子长度为8:"+maxProductAfterCutting(8));
        }
        /**
         * 测试边界值
         */
        private static  void test2() {
            System.out.println("绳子长度为0:"+maxProductAfterCutting(0));
            System.out.println("绳子长度为1:"+maxProductAfterCutting(1));
            System.out.println("绳子长度为2:"+maxProductAfterCutting(2));
            System.out.println("绳子长度为3:"+maxProductAfterCutting(3));
            System.out.println("绳子长度为4:"+maxProductAfterCutting(3));
        }
    }
    

    代码链接

    剑指Offer代码-Java

  • 相关阅读:
    有关token
    JQuery自定义resize事件代码解析
    vue--为网页添加动态响应背景
    如何查询数据库中所有表格,或者查询是否存在某个表格-mysql和oracle
    Foxmail: 错误信息::ssl连接错误, errorCode: 5,各种解决方案的大杂烩。
    [转] Hadoop入门系列(一)Window环境下搭建hadoop和hdfs的基本操作
    java连数据库和数据库连接池踩坑日记(二)-------数据库连接池c3p0
    java实现将汉字转为拼音
    Sublime 如何修改默认编码格式
    JSP 表单处理
  • 原文地址:https://www.cnblogs.com/haoworld/p/offer14-jian-sheng-zi.html
Copyright © 2020-2023  润新知