三分搜索的思想以及相应代码
三分搜索,其实就是求一个区间的最值问题,当然这个区间是有条件的。简单的说,就是把相应区间的点拿出来画到坐标纸上,形成的曲线要么是凹型的要么是凸型的,也就是最值两边是单调的并且最值只有一个。如果符合这个条件就可以用三分求最值了。
二分是把区间分成两块来求,那么三分就是把区间分成三块来求了。
那现在我们假设曲线是凸的,也就是序列a[n]是先递增后递减的。还是和二分一样先定义 int l,r,mid;mid=(r+l)/2;但是我们还要加一个变量int mmid;mmid=(mid+r)/2;这样整个待求区间就被分成[l,mid],[mid,mmid],[mmid,r]三个部分,下一步就是求最值了。我们是用a[mid]和a[mmid]两个值相比求出的;如果a[mid]>a[mmid],那么极值点x肯定在mmid的左边,如果a[mid]<a[mmid],那么x肯定在mid的右边,大家画一下图就清楚了,但是要注意mid<=mimd,因为mmid=(mid+r)/2得来的。那么不断重复知道a[mid]==a[mmid]就找到了最值点。当然这是在点离散的情况下,如果在连续的情况下只能到达fabs(a[mid],a[mmid])到达一定精度时退出。。
还有一个问题就是给你个函数怎么判断是凸函数还是凹函数,这里有一个数学方法,假设给出f(x),可以对f(x)求二阶导数f''(x),如果f''(x)>0,则该函数是凹函数,f''(x)<0,则函数是凸函数。
那现在给出示例代码,前提是凸函数:
int sanfen()
{
int l=0,r=n-1;
int mid,mmid;
while(l<r)
{
mid=(l+r)/2;
mmid=(mid+r)/2;
if(a[mid]>a[mmid])
r=mmid;
else
l=mid;
}
return (l+r)/2;
}