可恶的剪绳子问题

news/2024/12/13 16:21:34/

1. 剑指 Offer 14- I. 剪绳子

题目描述:给你一根长度为 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.1 方法一:动态规划

1.1.1 推导

  • 求最大值问题可考虑使用动态规划算法解决;
  • 动态规划解题的四大要素:状态定义、状态转移方程定义、初始状态以及返回结果;
  • 针对剪绳子问题,目的是将一个长度为n的绳子划分为m段,m段绳子最大乘积是多少,其中m>1,也就是将绳子需至少划分为两段;
  • 动态规划四要素:
    1)状态F(i):长度为i的绳子,划分后最大乘积为F(i);
    2)状态转移方程:F(i)=Max{F(i),F(i-j)*j,(i-j)*j};
    3)初始状态:F(2)=1,长度为2的绳子至少划分为两段,因此每段长度为1;
    4)返回结果:F(n),长度为n的绳子划分后的最大乘积;
  • 长度为n的绳子划分后最大乘积,可由长度小于n的绳子的划分最大乘积进一步得到。假设将绳子划分为两段,一段长度为j,另一段长度为n-j,长度为n-j的绳子可以进一步划分,也可以不划分,因此有对应两种情况:
    1)n-j的绳子不再划分,则划分乘积为j*(n-j);
    2)n-j的绳子继续划分,则划分乘积为j*F(n-j);

1.1.2 代码实现

class Solution {// 动态规划// 状态F(i):长度为i的绳子,划分后最大乘积为F(i)// 状态转移方程:F(i)=Max{F(i),F(i-j)*j,(i-j)*j}// 初始状态:F(2)=1public int cuttingRope(int n) {int[] maxPro=new int[n+1];// 初始状态maxPro[2]=1;// 状态转移for(int i=3;i<=n;i++){for(int j=1;j<i;j++){maxPro[i]=Math.max(maxPro[i],j*maxPro[i-j]);maxPro[i]=Math.max(maxPro[i],(i-j)*j);}}// 返回结果return maxPro[n];}
}

1.2 方法二:数学规律

1.2.1 数学推导

  • 针对剪绳子问题,目的是将一个长度为n的绳子划分为a段,a段绳子最大乘积是多少,其中a>1,也就是将绳子需至少划分为两段;

  • 假设将绳子划分为a段,分别为n1,n2,…,na,由下列算术几何均值不等式可知,当n1=n2=…=na时,n1,n2,…,na乘积最大;
    在这里插入图片描述

  • 由上述公式可知当将长度为n的绳子等长划分后,乘积最大。假设每段绳子长度为x,共划分为a段,则乘积为xa,a=n/x,进一步推导:
    在这里插入图片描述
    也就是当x1/x最大时,划分乘积最大,令y=x1/x,进行隐函数求导可得:
    在这里插入图片描述
    但我们知道绳子划分段长度需要为整数,则可取近似值x=3或x=2,分别将x代入y=x1/x可知当x=3时划分乘积最大

  • 有上述推导可总结划分原则:
    1)尽可能将绳子划分为长度为3的段,共t段,剩余绳子长度有0,1,2三种可能;
    2)如果剩余绳子长度为0,说明绳子原长度正好为3的倍数,此时得到最优解3t
    3)如果剩余绳子长度为2,则将剩余部分看做整体,不再进一步划分,则划分乘积为3t*2;
    4)如果剩余绳子长度为1,则将长度为3的子段取出一个与剩余部分总长度为4(将其划分为两段长度为2的子段,因为此时2*2>1*3),则划分乘积为3t-1*2*2;

参考https://leetcode.cn/problems/jian-sheng-zi-ii-lcof/solution/mian-shi-ti-14-ii-jian-sheng-zi-iitan-xin-er-fen-f/

1.2.2 代码实现

class Solution {// 数学推导:将绳子尽可能按照长度为3的段分割,乘积最大public int cuttingRope(int n) {if(n<=2){return 1;}// 特殊情况if(n==3){return 2;}int res=n/3;  // 按照3分割,最多得到多少段int mod=n%3;  // 只有0,1,2三种情况if(mod==0){return (int)Math.pow(3,res);  // 说明是3的倍数}else if(mod==1){return (int)Math.pow(3,res-1)*4; // 3a+1,把最后两段3+1划分为2+2}else{return (int)Math.pow(3,res)*2; // 3a+2}}
}

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

题目描述:给你一根长度为 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。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

2.1 推导

  • 基础推导如1.2.1节所示;
  • 此处与上一道题不同的是,n的取值范围变大,因此在求3t时可能会发生边界值溢出的情况;
  • 基于取余运算如下图所示的性质,可通过循环取余的方法解决取值范围溢出的问题;
    在这里插入图片描述

2.2 代码实现

class Solution {public int cuttingRope(int n) {if(n<=2){return 1;}if(n==3){return 2;}int base=1000000007;int res=n/3;int mod=n%3;if(mod==1){res-=1;}// 计算pow(3,res)long target=1;while(res-->0){target=((target%base)*3)%base;}if(mod==0){return (int)(target%base); }else if(mod==1){return (int)((target*4)%base);}else{return (int)((target*2)%base);}}
}

http://www.ppmy.cn/news/794704.html

相关文章

没有为 vtkGUISupportQt-8.2.dll 加载的符号文件

没有为 vtkGUISupportQt-8.2.dll 加载的符号文件 在你的main函数前&#xff0c;加上&#xff1a; #include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL2) VTK_MODULE_INIT(vtkInteractionStyle) #include "VtkDemo_02.h" #include <QtWidgets/…

elementUI 返回上一个页面

elementUI 返回上一个页面 There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog content is all parallel goods. Those who are worried about being cheated should leave quickly. ba…

为什么在数据库中查询时count(1)和count(*)都能达到同样的效果,而count(1)效率更高?

具体原因如下&#xff1a; 1. 常量值 vs 通配符&#xff1a; COUNT(1)使用的是一个常量值1&#xff0c;而COUNT(*)使用的是通配符*&#xff0c;表示所有的列。由于在进行行统计时&#xff0c;不需要具体的列数据&#xff0c;只需要计算满足条件的行数&#xff0c;所以使用任何…

leetcode-3-无重复字符的最长子串

题意描述&#xff1a; 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示意&#xff1a; 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”&#xff0c;所以其长度为 3。 示例 2: 输入: s “bbbbb” 输出: 1 解释: …

认识文件操作与IO

文章目录 认识文件文件夹文件路径文件分类 文件操作File类构造方法常用方法 字节流IOInputStream常用方法 FileInputStream构造方法FileInputStream实例 OutputStream方法 FileOutputStream 字符流IO 认识文件 我们平时所说的文件指的是存在硬盘上的文件&#xff0c;我们平时的…

阿里云服务器架构X86计算、ARM、GPU/FPGA、裸金属和超级计算集群

阿里云服务器架构有什么区别&#xff1f;X86计算、ARM计算、GPU/FPGA/ASIC、弹性裸金属服务器、超级计算集群有什么区别&#xff1f;阿里云服务器网分享云服务器ECS架构详细说明&#xff1a; 目录 阿里云服务器ECS架构说明 X86计算 ARM计算 GPU/FPGA/ASIC 弹性裸金属服务…

Flutter 轮播图 flutter_swiper属性说明使用

今天分享的内容是关于图片轮播的实现&#xff0c;使用到的库是flutter_swiper&#xff0c;如果有出现空检查报错的&#xff0c;可以使用flutter_swiper_null_safety 轮播图效果如下&#xff1a; 先贴出基本参数详解&#xff1a; 参数说明itemBuilder列表的构造indicatorLayou…

HTML显示器泛白,三星显示器屏幕发白怎么办

在有些时候我们的三星显示器屏幕发白了&#xff0c;这该怎么办呢?下面就由学习啦小编来为你们简单的介绍三星显示器屏幕发白的原因及解决方法吧!希望你们喜欢! 三星显示器屏幕发白的原因及解决&#xff1a; 软件问题&#xff1a; 显卡的驱动没有装好。其实即使没有驱动&#x…