关于凸函数求最大值的下标的小讨论(斐波那契优选法/二分法/三分法)
问题:假设F是定义在整数集合的函数,并且F在区间[L,R]中先严格单调递增再严格单调递减,求最大值下标。
方法一:三分法
对于区间[ L , R ] ,在区间取左右两个三等分点M1,M2;
V1=F(M1) V2=F(M2) 比较V1,V2的值.
若 V1<V2 则最大值一定不在M1左侧,继续判断新区间[M1,R]
若 V1>V2 则最大值一定不在M2右侧,继续判断新区间[L,M2]
V1=V2时,为了写代码方便,可归入上面任意一类。
于是每次去掉区间的33.3%,并且计算两次F
F的计算次数约为 2*log1.5 ( n),约为斐波那契优选法的2倍多一点
方法二:斐波那契优选法(三分法的优化)
斐波那契优选法的重点就在于代码的重用,
令区间长度R-L为某个斐波那契数(R不足时扩充R,使F对大于R的值都返回F[R]来避免大于R的值干扰结果)
用D[n]表示斐波那契数列的第n个数。
假设区间长度为D[n],那么取 M1=D[n-2], M2=D[n-1].
V1=F(M1) V2=F(M2) 比较V1,V2的值.
若V1<V2 最大值不在M1左侧,继续判断新区间[M1,R] 。
但是,此时,新区间的newM1 = 旧的M2 于是newV1的值我们已经知道了,等于V2,所以少了一次对F的计算(总共就两次,所以是少了一半)。
见下图:两行分别是旧的和新的L,M1,M2,R.其中L是绝对地址,M1,M2,R都是相对于L的地址。
另一边也是这样,就不赘述了。
V1=V2时,需归入V1>V2的区间,这是为了优先删除右区间,因为右区间是有赘余的。
由于是用的斐波那契数,由斐波那契数之间的比例关系,得到,每次删除的区间其实是38.2%,并且只用计算一次F
所以各方面都优于三分法。F的计算次数约为 log1.618 (n)
给出一个例子,在区间[0,1000000]中寻找最大值的过程:
方法三:二分法
由于区间只有上升和下降两种趋势,由F(n+1)-F(n)可判断n在极值点左侧还是右侧
所以只要二分求满足F(n+1)>F(n)的最大n,然后再+1就是答案。
每次删除一半,但每次要计算两个F,所以F的计算次数约为 2*log2(n),约为斐波那契优选法的1.4倍。
对于0到100000000的区间,三种方法的效率为:
若由F(n)推出F(n+1) 的时间相对于直接计算F(n)的时间可以忽略不计的话,二分法的F的执行次数就可以减半,这时二分法是最优的解。
如果不符合这个条件的话,还是斐波那契优选法最优,只是写起来比二分法麻烦一点。
最后附上代码:
int Count;
int F(int x){++Count;return 1000000000-abs(x-375832);
}
int Find(int Low,int Hi){int L=Low,M1,M2,R;//闭区间[L,L+R] ,L是绝对地址,M1,M2,R 是相对地址 int VL,V1,V2,VR;#define Func(x) (x<Hi?F(x):F(Hi))M1=0;M2=1;R=1; while(R <Hi-Low){int t=M2+R;M1=M2;M2=R;R=t;}Count=0;VL=Func(L);V1=Func(L+M1);V2=Func(L+M2);VR=Func(L+R);while(R>3){//printf("实际区间:%6d %6d %6d %6d 相对区间:0 %6d %6d %6d\n",L,L+M1,L+M2,L+R,M1,M2,R);if(V1<V2){//L F[n-2] F[n-1] F[n] // L F[n-3] (新区间:F[n-2]) F[n-1] L+=M1;R=M2;M1=M2-M1;M2=R-M1;VL=V1;V1=V2;V2=Func(L+M2);}else{//L F[n-2] F[n-1] R//L (F[n-3]) F[n-2] RR=M2;M2=M1;M1=R-M2;VR=V2;V2=V1;V1=Func(L+M1);}}#undef Func//printf("\n斐波那契优选法:执行F函数%d次 ",Count);if(VL>=VR&&VL>=V1&&VL>=V2) return L;if(V1>=V2&&V1>=VR) return L+1;if(V2>=VR) return L+2;return L+3;
}
int BinaryFind(int Low,int Hi){//[Low,Hi]int L=Low,R=Hi,M;//左闭右开:[L,R) 求最大的x使得F[x+1]>F[x];Count=0;while(L+1<R){M=(L+R)>>1;if(F(M)<F(M+1)) L=M;else R=M;}int ANS=F(L+1)>F(L)?R:L;//printf("\n二分法:执行F函数%d次 ",Count); return ANS;
}
int TriFind(int Low,int Hi){int L=Low,M1,M2,R=Hi;int V1,V2;Count=0;while(L +3 <R){M1=L+(R-L)/3;M2=M1+(R-L)/3;V1=F(M1);V2=F(M2);if(V1==V2) {L=M1;R=M2;}else if(V1<V2) L=M1;else R=M2;}int H[4];for(int i=0;i<4;++i) H[i]=F(L+i);//printf("\n三分法:执行F函数%d次 ",Count); if(H[0]>=H[1]&&H[0]>=H[2]&&H[0]>=H[3]) return L;if(H[1]>=H[2]&&H[1]>=H[3]) return L+1;if(H[2]>H[3]) return L+2;return L+3;
}
关于凸函数求最大值的下标的小讨论(斐波那契优选法/二分法/三分法)相关推荐
- 蓝桥杯python组--基础训练---求输入的第n个,斐波那契数
文章目录 题目 思路1: 结果 思路2: 结果 思路3 结果 思路4 结果 思路5 结果 思路6 结果 题目 求输入的第n个,斐波那契数 斐波那契数:斐波那契数列(Fibonacci sequence ...
- php算法求出兔子数列,PHP算法:斐波那契数列的N种算法
前言 前段时间,遇到优化计算斐波那契数列的常规递归方法,但是一时间并没有及时想到很好的方法,所以后面查找了相关资料,总结了多种计算解法,所以分享出来,和大家一起交流学习. 斐波那契数是什么 斐波那契数 ...
- c语言斐波那契数列前20项每行5个数,求c++:源程序。前20项斐波那契数列 ,要求输出的时候每行输出五个...
解答过程如图所示: 工作原理:C++语言的程序因为要体现高性能,所以都是编译型的.但其开发环境,为了方便测试,将调试环境做成解释型的.即开发过程中,以解释型的逐条语句执行方式来进行调试,以编译型的脱离 ...
- 由递推关系式用差分方程的方法得到通项公式实现求斐波那契数列的第n项;迭代、递归、栈、差分方程之间的本质联系以及由推广的迭代法解决“变态青蛙跳台阶”问题;汉诺塔问题的数字特征以及用递归解决的原理推导。
最近几天在研究算法中一个比较基础且突出的问题,就是关于"递推关系式.递归.迭代.序列前k项和"之间的区别与联系. 一.斐波那契数列与差分方程 首先我们考察一个经典的算法,求斐波那契 ...
- fibonacci斐波那契数列详解 递归求Fn非递归求Fn求n最近的斐波那契数
斐波那契fibonacci 斐波那契额数列即前两项F(0)和F(1)都是1,之后的每一项都是前两项相加和即F(3)=2,F(4)=3,F(5)=5; 通项公式:F(n+2)=F(n+1)+F(n). ...
- 2019年pta作业第二题——求最大值及其下标
7-2 求最大值及其下标 (20 分) 本题要求编写程序,找出给定的n个数中的最大值及其对应的最小下标(下标从0开始). 输入格式: 输入在第一行中给出一个正整数n(1<n≤10).第二行输入n ...
- 7-2 求最大值及其下标
7-2 求最大值及其下标 (20 分) 本题要求编写程序,找出给定的n个数中的最大值及其对应的最小下标(下标从0开始). 输入格式: 输入在第一行中给出一个正整数n(1<n≤10).第二行输入n ...
- 求最大值及其下标编程总结
-2 求最大值及其下标 (20 分) 本题要求编写程序,找出给定的n个数中的最大值及其对应的最小下标(下标从0开始). 输入格式: 输入在第一行中给出一个正整数n(1<n≤10).第二行输入n个 ...
- 练习7-2 求最大值及其下标
题目要求 练习7-2 求最大值及其下标 (20 分) 本题要求编写程序,找出给定的n个数中的最大值及其对应的最小下标(下标从0开始). 输入格式: 输入在第一行中给出一个正整数n(1<n≤10) ...
最新文章
- dfasdfasdfas
- ORACLE DBA的职责
- STM32F103ZET6 蜂鸣器、按键
- LeetCode 26.删除排序数组中的重复项
- 方法二 、属性 CLR学习第九课
- LVS负载均衡群集之NAT模型DR模型
- mysql数据库编程第六章试题_2016年计算机二级MySQL数据库试题及答案
- vim中字符串的替换
- 用python实现文件加密功能
- 【小样本基础】N-way K-shot 模式和训练策略
- SAP 运维 集团化公司SAP系统运维管理体系建设方案
- Arun Murthy谈Apache YARN
- jquery插件zoom
- Unsupported major.minor version 52.0 解决方案
- Windows Server 中 DNS 服务器的新增功能
- Java解析JSON格式数据
- 我,程序员,32岁失业后干啥都赔钱,月薪2万的好日子一去不返
- 在自己的app中打开淘宝
- UAC1.0和UAC2.0区别
- cesium中缓冲区分析