本文参考自《剑指offer》一书,代码采用Java语言。

更多:《剑指Offer》Java实现合集  

题目

  给你一根长度为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时,最大乘积只能为0;

  当n=2时,最大乘积只能为1;

  当n=3时,最大乘积只能为2;

  当n=4时,可以分为如下几种情况:1*1*1*1,1*2*1,1*3,2*2,最大乘积为4;

  往下推时,发现n≥4时,可以把问题变成几个小问题,即:如果把长度n绳子的最大乘积记为f(n),则有:f(n)=max(f(i)*f(n-1)),0<i<n。所以思路就很容易出来了:从下往上推,先算小的问题,再算大的问题,大的问题通过寻找小问题的最优组合得到。

  其实这就是动态规划法,以下是动态规划法的几个特点:

  1.求一个问题的最优解

  2.整体问题的最优解依赖各子问题的最优解

  3.小问题之间还有相互重叠的更小的子问题

  4.为了避免小问题的重复求解,采用从上往下分析和从下往上求解的方法求解问题

  贪婪算法依赖于数学证明,当绳子大于5时,尽量多地剪出长度为3的绳子是最优解。

测试用例

  1.功能测试(长度大于5)

  2.边界值测试(长度1,2,3,4)

完整Java代码

(含测试代码,测试代码参考:CuttingRope.cpp

/**
*
* @Description 面试题14:剪绳子
*
* @author yongh
* @date 2018年9月17日 上午9:37:41
*/ // 题目:给你一根长度为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。 public class CuttingRope {
// ======动态规划======
public int maxProductAfterCutting_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; // 开始从下到上计算长度为i绳子的最大乘积值product[i]
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];
} // =======贪婪算法========
public int maxProductAfterCutting_solution2(int length) {
if (length <= 1)
return 0;
if (length == 2)
return 1;
if (length == 3)
return 2;
int timesOf3 = length / 3;
int timesOf2 = 0;
if (length - timesOf3 * 3 == 1) {
timesOf3--;
// timesOf2=2; //错误!
}
timesOf2 = (length - timesOf3 * 3) / 2;
return (int) (Math.pow(3, timesOf3) * Math.pow(2, timesOf2));
} // =====测试代码======
void test(String testName, int length, int expected) {
if (testName != null)
System.out.println(testName + ":");
if (maxProductAfterCutting_solution1(length) == expected) {
System.out.print(" 动态规划:" + "passed ");
} else {
System.out.print(" 动态规划:" + "failed ");
} if (maxProductAfterCutting_solution2(length) == expected) {
System.out.println("贪婪算法:" + "passed ");
} else {
System.out.println("贪婪算法:" + "failed ");
}
} void test1() {
test("test1", 1, 0);
} void test2() {
test("test2", 2, 1);
} void test3() {
test("test3", 3, 2);
} void test4() {
test("test4", 4, 4);
} void test5() {
test("test5", 5, 6);
} void test6() {
test("test6", 10, 36);
} void test7() {
test("test7", 50, 86093442);
} public static void main(String[] args) {
CuttingRope demo = new CuttingRope();
demo.test1();
demo.test2();
demo.test3();
demo.test4();
demo.test5();
demo.test6();
demo.test7();
}
}

  

test1:
动态规划:passed 贪婪算法:passed
test2:
动态规划:passed 贪婪算法:passed
test3:
动态规划:passed 贪婪算法:passed
test4:
动态规划:passed 贪婪算法:passed
test5:
动态规划:passed 贪婪算法:passed
test6:
动态规划:passed 贪婪算法:passed
test7:
动态规划:passed 贪婪算法:passed

CuttingRope

收获

  1.最优解问题,经常使用动态规划法,关键要刻画最优解的结构特征(本题的f(n)),从下往上计算最优解的值,没有思路时,从简单情况先算一下。

  2.动态规划法中,子问题的最优解一般存放于一个数组中。

  3.本题贪婪规划的代码中,timeOf2别忘记等于1的情况。

复习时补充:

1. 动态规划法可以直接令 f(n)=max{f(n-2)*2,f(n-3)*3} 就可以了。

2. 贪婪算法,第51-58行可改为

		int timesOf3=n/3;
if(n%3==0)
return (int)Math.pow(3, timesOf3);
if(n%3==1)
return (int)Math.pow(3, timesOf3-1)*4; //是乘以4,不是2
return (int)Math.pow(3, timesOf3)*2;

  

更多:《剑指Offer》Java实现合集  

【Java】 剑指offer(13) 剪绳子的更多相关文章

  1. 剑指 Offer 14- II. 剪绳子 II + 贪心 + 数论 + 快速幂

    剑指 Offer 14- II. 剪绳子 II 题目链接 因为有取模的操作,动态规划中max不能用了,我们观察:正整数从1开始,但是1不能拆分成两个正整数之和,所以不能当输入. 2只能拆成 1+1,所 ...

  2. 剑指 Offer 14- I. 剪绳子 + 动态规划 + 数论

    剑指 Offer 14- I. 剪绳子 题目链接 还是343. 整数拆分的官方题解写的更清楚 本题说的将绳子剪成m段,m是大于1的任意一个正整数,也就是必须剪这个绳子,至于剪成几段,每一段多长,才能使 ...

  3. 剑指 Offer 14- II. 剪绳子 II

    剑指 Offer 14- II. 剪绳子 II 给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m.n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]... ...

  4. [剑指offer]14-1.剪绳子

    14-1.剪绳子 方法一 动态规划 思路:递归式为f(n)=max(f(i), f(n-i)),i=1,2,...,n-1 虽然我现在也没有彻底明白这个递归式是怎么来的,但用的时候还是要注意一下.f( ...

  5. 剑指offer:剪绳子

    题目描述: 给你一根长度为n的绳子,请把绳子剪成m段(m.n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m].请问k[0]xk[1]x...xk[m]可 ...

  6. Go语言实现:【剑指offer】剪绳子

    该题目来源于牛客网<剑指offer>专题. 给你一根长度为n的绳子,请把绳子剪成整数长的m段(m.n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],-,k[ ...

  7. 剑指offer——15剪绳子

    题目描述 给你一根长度为n的绳子,请把绳子剪成m段(m.n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m].请问k[0]xk[1]x...xk[m]可能 ...

  8. 剑指offer:剪绳子(找规律,贪心算法,动态规划)

    1. 题目描述 /* 题目描述 给你一根长度为n的绳子,请把绳子剪成m段(m.n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m].请问k[0]xk[1] ...

  9. 【剑指offer】剪绳子

    题目描述 给你一根长度为n的绳子,请把绳子剪成m段(m.n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m].请问k[0]xk[1]x...xk[m]可能 ...

随机推荐

  1. CRLF攻击的一篇科普:新浪某站CRLF Injection导致的安全问题(转)

    转:https://www.leavesongs.com/PENETRATION/Sina-CRLF-Injection.html 新浪某站CRLF Injection导致的安全问题 PHITHON ...

  2. POJ2421 Constructing Roads【最小生成树】

    题意: 有N个点,有些点已经连接了,然后求出所有点的连接的最短路径是多少. 思路: 最小生成树的变形,有的点已经连接了,就直接把他们的权值赋为0,一样的就做最小生成树. 代码: prime: #inc ...

  3. pt-table-checksum检测不出主从差异处理

    几个月前写过pt-table-checksum 3.0.4检测不出主从差异数据,当时的解决方案是使用旧版本,另一个挫方法是自行设置binlog_format='STATEMENT'.现在已经发布到3. ...

  4. DSO windowed optimization 代码 (1)

    这里不想解释怎么 marginalize,什么是 First-Estimates Jacobian (FEJ).这里只看看代码,看看Hessian矩阵是怎么构造出来的. 1 优化流程 整个优化过程,也 ...

  5. css 背景图片自适应元素大小

    一.一种比较土的方法,<img>置于底层. 方法如下: CSS代码: HTML: <img src="背景图片路径" /> <span>字在背景 ...

  6. js的正则表达式编程,悬赏解决下面的问题

    悬赏解决下面的问题 1.切分url 2.将时间日期 转化为 yyyy-MM-dd的模式和可逆性 3.数据的千分位和可逆性 4.用C#或者nodejs检索如下的模式 h1{ border:1px sol ...

  7. 【逆向工具】IDA使用6-签名文件制作

    0x1 签名文件制作的方法: 找到静态编译的程序库 使用IDA中的fair工具包,对静态库操作,生成特征库(IDA6.8 是flair68.zip) 0x2 步骤 第一步:使用pcf生成对应静态库的p ...

  8. 【转】Python之日期与时间处理模块(date和datetime)

    [转]Python之日期与时间处理模块(date和datetime) 本节内容 前言 相关术语的解释 时间的表现形式 time模块 datetime模块 时间格式码 总结 前言 在开发工作中,我们经常 ...

  9. python操作mysql数据库的常用方法使用详解

    python操作mysql数据库 1.环境准备: Linux 安装mysql: apt-get install mysql-server 安装python-mysql模块:apt-get instal ...

  10. Android studio下将项目代码上传至github包括更新,同步,创建依赖

    AS中设置GIT 一.开篇 本文讲如何使用Android Studio将项目上传到github,虽然讲上传github的文章很多,但是大部分都是使用Git Bash命令行,虽然效率高些,但是有点麻烦, ...