【算法分析】之重新认识三分-----求极值(极大值和极小值)
被虐了。不过也是经常的事。
好了,开始讲。我们都知道二分可以求具有单调性的函数中的某个值。比如f(x)是具有单调性的,我们可以通过二分求f(x)==y的时候x的值是多少(已知y求x)。
但是为什么可以这么做呢?假设f(x)的单调性递增。
首先看二分的伪 代码:
bool binary_search(int l,int r,int y,int &ans) |
观察之后发现每次对于L和R的赋值操作都保证值在[L,R]这个区间内,这样就可以逼近要求的那个值。
好了,二分简单说到这。
现在提出一个问题。
现在我想求这个抛物线的极大值。
如果继续使用二分的话无法得出有效的答案,因为单纯的二分每次对于L或R的操作无法确定答案位于[L,R]区间内
因为这个图某个部分是单调上升而某个部分是单调递减的。
但是我们可以抓住二分的本质。
现在我想问。二分的本质是什么?
每次对于L或R的操作可以保证要求的值位于[L,R]区间中,这样迭代到最后是一定可以求到值的,以[L,R]为目标,mid为参考不断缩小[L,R]的范围。
知道了这一点我们可以考虑怎么求这个函数的极值了。
一个mid不行,那么我用mid的mid呢?
假设
mid=(L+R)/2;
midmid=(L+mid)/2;
那么可能出现的情况在图中所示,mid为红色(两种情况),midmid为褐色
当发生这种情况的时候,我们一定可以保证,答案位于[midmid,R]这个区间
这时我们就可以这么做:
当f(midmid)<f(mid) 令L=midmid;这样一定可以保证答案位于[L,R]这个区间内
当然了,还有f(midmid)>f(mid)的情况。见图。
考虑到这种情况
当f(midmid)>f(mid)时,我们令R=mid
考虑到这里,其实还有f(midmid)=f(mi)的情况。这种也很好解决
当f(midmid)=f(mid)时,我们令L=midmid或者R=mid;
到这里我们就有了一个很清晰的直观解决方法
假设我们一开始就可以确认极值位于[0,n]这个范围内
伪代码
1.令L=0,R=n;
2.令mid=(L+R)/2,midmid=(L+mid)/2;(除法为向下取整
3.计算若f(midmid)<f(mid),则令L=midmid;
否则令R=mid;
4.若L=R则算法结束,结果为L
否则转2
到这里我们还可以继续。新问题:
求下面这个函数的任意极大值
只需要求任意一个极大值,
其实是和求抛物线一样的算法。
为什么可以?
你可以按照我分析求抛物线所得出的算法方法来分析这题。
图:
假设:红色为mid,褐色为midmid
图:
其实算法都是一样的。好了说完了。