二分与三分

1.介绍一下二分

  • 什么是二分?

二分法,顾名思义,就是一次分成两份,实际也就是这样(其实并不是

咳咳,二分法,就是在一个单调有序的序列(或者集合,函数,只要是单调有序的就行)中查找一个解,每次把当前的范围从中间劈开分为左右两部分,然后判断解在哪个部分中并且不断地调整上下界,直到找到答案。

二分是一种常用的算法,常常是我们解决问题的突破口(在你没有思路的时候暴力二分求解)。

二分的基本用途是在单调序列或者单调函数中进行查找操作。因此如果问题的答案具有单调性,就可以考虑二分判定

是的,二分和判定

如果你只二分而不判定的话,就无法继续二分,也无法退出二分,就相当于你卡在了一个非常尴尬的位置上

所以二分的时间复杂度为O(二分次数*单次判定的复杂度)

如果是在正整数上二分的话,二分次数就是log n,判定结束二分时只需要看看目前左右端点是否一样就行了

而如果是在实数上二分的话,就需要判定精度,abs(l-r)是否小于给定的精度

  • 二分要注意的事项

1.单调性,单调性,单调性(重要的事情说三遍)

  只有具有单调性的集合或者函数才可以用二分,否则就算你分出来了区间也不能进行下一步的操作。如果当前给定的数据不具有单调性,你不妨给他排一下序

2.虽然你使用了二分,而且单纯的二分复杂度也不是很高,但你还是要好好写一写检查的函数,否则还是会TLE

2.二分的常见模型

1.二分答案

  看到最小值最大或者是最大值最小的问题,基本上就是二分没跑了,需要在确定答案后,配合其他算法检查这个答案是否合理

2.二分查找

  用具有单调性的布尔表达式求解分界

3.代替三分

  有的时候对于一些单峰函数,我们可以用二分导函数的方法求解函数极值(什么是导函数?详情参见百度百科或高中选修2-3或高等数学(一)

3.二分板子

1.整数定义域上的二分

代码:

bool check(int l)
{
    //......
}

int erfen(int 1,int n)
{
    int l=1,r=n;
    int ans;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(check(mid)) r=mid;
        else l=mid;
    }
    return l;
 } 

2.实数定义域上的二分

代码:

double eps=0.001;//这个随着题目要求而改变 

bool check(double l)
{
    //......
}

double erfen(double 1,double n)
{
    double l=1,r=n;
    double ans;
    while(fabs(l-r)>eps)
    {
        double mid=(l+r)/2.0;
        if(check(mid)) r=mid;
        else l=mid;
    }
    return l;
 } 

(在你没有思路的时候暴力二分求解

原文地址:https://www.cnblogs.com/lcezych/p/10986720.html