首页 > 代码库 > 三分查找

三分查找

可以用三分法求一个凸函数或者凹函数的最大或最小值。

主要思路是对整个区间进行三等分,切分点记为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     }

 

三分查找