三分查找
可以用三分法求一个凸函数或者凹函数的最大或最小值。
主要思路是对整个区间进行三等分,切分点记为m1, m2,以凸函数为例,如果f(m1)>f(m2),最大值一定不会在 [m2, right],所以右界可以更新为m2,类似的,如果f(m1)<f(m2),最大值一定不会在 [left, m1],所以左界可以更新为m1,如果f(m1)==f(m2),则两个更新任选其一即可。
有一个小细节要注意一下,为了防止左右相距很近时停止更新((right-left)/3==0), 我们可以对这个式子向上取整,即:(right-left+2)/3, 或者在后面更新left or right时多移动一位,对left/right采用其中任意一种方法即可。
例子:
1 //三分法 2 //三分求凹函数的极小值 3 double ternarySearch(double l,double r) 4 { 5 //EPS是精度限制(eg.1e-5) 6 while(r-l>EPS) 7 { 8 double ll=(2*l+r)/3; 9 double rr=(l+2*r)/3; 10 double ans1=equ(ll); 11 double ans2=equ(rr); 12 if(ans1>ans2) 13 l=ll; 14 else 15 r=rr; 16 } 17 return l; 18 } 19 20 //三分求数列中最大值(数据凸函数排序分布) 21 int find_max() { 22 int left=0,right=length-1; 23 while(right-left>=2){ 24 int m1=left+(right-left)/3; 25 //防止m1&m2停止更新,采用(right-left+2),因为有可能right-left=2 26 int m2=right-(right-left+2)/3; 27 if(data[m1]>=data[m2]){ 28 right=m2; 29 } 30 else{ 31 //防止left停止更新 32 left=m1+1; 33 } 34 } 35 if(data[left]>data[right]){ 36 return left; 37 } 38 else{ 39 return right; 40 } 41 }