当前位置: 首页 > news >正文

剪绳子 -- java

题目描述

给你一根长度为 n 的绳子,请把绳子减成 m 段(m、n都是整数,n > 1 并且 m > 1, 每段绳子的长度记为k[0], k[1],…,k[m]。

请问k[0]*k[1]k[2]…*k[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成的长度为2、3、3三段,此时得到的最大乘积是18。

题目考点

  • 考察应聘者的抽象建模能力。应聘者需要把一个具体的场景抽象成一个能够用动态规划或者贪婪算法解决的模型。
  • 考察应聘者对动态规划和贪婪算法的理解。能够灵活运用动态规划解决问题的关键是具备从上到下分析问题、从下到上解决问题的能力,而灵活运用贪婪算法则需要扎实的数学基本功。

解题思路

动态规划

设 f(n) 代表长度为n的绳子剪成若干段的最大乘积,如果第一刀下去,第一段长度是 i ,那么剩下的长度就是 n-i ,那么f(n)=max{f(i)f(n-i)}。假设f(i) 确定,我们就要继续求f(n-i)的最优解,我们可以看出剪绳子是最优解问题,其次,大问题包含小问题,并且大问题的最优解包含着小问题的最优解,所以可以使用动态规划求解问题,并且从小到大求解,把小问题的最优解记录在数组中,求大问题最优解时就可以直接获取,避免重复计算。

贪婪算法

尽可能多剪长度为 3 的绳子,并且不允许有长度为 1 的绳子出现,如果出现了,就从已经切好长度为 3 的绳子中拿出一段与长度为 1 的绳子重新组合,把它们切成两段长度为 2 的绳子。

证明:

当 n >= 5 时,所有f(n)都可以表示为3(n - 3)或者2(n - 2),又因为3(n - 3) - 2(n - 2) = n - 5 >= 0。因此把长度大于 5 的绳子切成两段,令其中一段长度为 3 可以使得两段的乘积最大。

当 n = 4时,拆成 2 * 2 最大。

代码

动态规划

public class MaxProductAfterCutting {
    public static int maxProductAfterCutting_solution1(int length) {
        // 得到 绳子长度小于等于3的显然的最优解
        if (length < 2) {
            return 0;
        } else if (length == 2) {
            return 1;
        } else if (length == 3) {
            return 2;
        }

        //创建数组存储子问题最优解
        int[] products = new int[length+1];
        for (int i = 0; i <= 3; i++) {
            products[i] = i;
        }

        int max = 0;
        // 开始求解每一个绳子长度的最优解
        for (int i = 4; i <= length; i++) {
            max = 0;
            for (int j = 1; j <= i/2; j++) {
                int product = products[j] * products[i-j];
                if (max < product) {
                    max = product;
                }
            }
            products[i] = max;
        }

        return products[length];
    }

    // 测试
    public static void main(String[] args) {
        System.out.println(maxProductAfterCutting_solution1(8));
    }
}

贪婪算法

public class MaxProductAfterCutting {
    public static int maxProductAfterCutting_solution2(int length) {
        // 得到 绳子长度小于等于3的显然的最优解
        if (length < 2) {
            return 0;
        } else if (length == 2) {
            return 1;
        } else if (length == 3) {
            return 2;
        }

        // 尽可能多地剪去长度为3的绳子段
        int timesOf3 = length / 3;
        // 当绳子最后剩下的长度为4的时候,不能再剪去长度为3的绳子段
        // 此时更好的方法是把绳子剪成长度为2的两段,因为 2x2 > 3x1
        if ((length - timesOf3 * 3) == 1) {
             timesOf3--;
        }
        int timesOf2 = (length - timesOf3*3) / 2;
        return (int)(Math.pow(3, timesOf3)) * (int)(Math.pow(2, timesOf2));
    }

    // 测试
    public static void main(String[] args) {
        System.out.println(maxProductAfterCutting_solution2(8));
    }
}

补充

动态规划

如果面试题是求一个问题的 最优解(通常是求最大值或者最小值)(特点一),而且该问题 能够分解成若干个子问题(特点二),并且 子问题之间还有重叠的更小的子问题(特点三),就可以考虑用 动态规划 来解决这个问题。从上往下分析问题,从下往上求解问题,这是动态规划求解的问题的第四个特点。

贪婪算法

当我们应用贪婪算法解决问题的时候,都一步都可以做出一个贪婪的选择,基于这个选择,我们确定能够得到最优解。为什么某种贪婪选择能够得到最优解? 这是我们应用贪婪算法时都需要问的问题,需要用数学方式来证明贪婪选择是正确的。


来自:
《剑指Offer》
Coding-Interviews/剪绳子.md at master · todorex/Coding-Interviews

相关文章:

  • 二进制中1的个数 -- java
  • mysql 5.7修改root登录密码
  • 关于 Double.compare()
  • mac关闭f11显示桌面快捷键
  • java中如何比较两个浮点型大小
  • 了解 BigDecimal.valueOf(double val)与new BigDecimal(double val) 的区别
  • 数值的整数次方 -- java
  • Could not get a resource from the pool 的原因之一
  • 打印从1到最大的n位数 -- java
  • 删除链表节点 -- java
  • npm 查看是否安装了某个包
  • 正则表达式匹配 -- java
  • 表示数值的字符串 -- java
  • 调整数组顺序使奇数位于偶数前面 -- java
  • 链表中倒数第K个节点 -- java
  • 2017 前端面试准备 - 收藏集 - 掘金
  • CSS 三角实现
  • Effective Java 笔记(一)
  • Javascript Math对象和Date对象常用方法详解
  • JavaScript标准库系列——Math对象和Date对象(二)
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • js算法-归并排序(merge_sort)
  • Netty源码解析1-Buffer
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • nodejs:开发并发布一个nodejs包
  • php面试题 汇集2
  • Python学习之路13-记分
  • Service Worker
  • 阿里研究院入选中国企业智库系统影响力榜
  • 闭包--闭包作用之保存(一)
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 记一次用 NodeJs 实现模拟登录的思路
  • 网页视频流m3u8/ts视频下载
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 云大使推广中的常见热门问题
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • #git 撤消对文件的更改
  • #QT(一种朴素的计算器实现方法)
  • (6)设计一个TimeMap
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (七)c52学习之旅-中断
  • (算法)前K大的和
  • (一)WLAN定义和基本架构转
  • *ST京蓝入股力合节能 着力绿色智慧城市服务
  • .NET Core Web APi类库如何内嵌运行?
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件
  • .NET业务框架的构建
  • .net中生成excel后调整宽度
  • .skip() 和 .only() 的使用
  • /etc/apt/sources.list 和 /etc/apt/sources.list.d
  • :中兴通讯为何成功