zoukankan      html  css  js  c++  java
  • (ACM模板)二分查找

    二分是一个比较大的概念,广义上把东西(可能是问题,区间等等)一分为二都是二分。

    这里讲二分查找。

    据说只有10%的程序员能写对二分。虽然二分是一个简单的算法。但是其变化和细节却并不简单。

    整数二分:

    因为mid取整的问题,如果不细心有可能会死循环。

    所以写二分查找需要仔细考虑 答案在开/闭区间?mid向上/下取整?循环结束条件?这些选择的取舍不同会导致二分的写法不同,没有说必须哪一种是正确的。掌握自己喜欢的写法即可。

    这里的二分保证答案必须在[L,R]闭区间,循环借宿条件为(L==R),答案下标为 L 。

    代码如下,其中细节还是值得细细琢磨。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=100000;
    int n,q,a[N],l,r; 
    
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        
        //查找满足>=q的第一个数(x或x的后继)
        //因为是>=蓑衣用向下(即L)取整
        //注意要保证答案在[L,R]区间,这里满足(a[mid]>=q)即mid在答案区间内r=mid,else即mid不在答案区间内l=mid+1舍弃mid 
        scanf("%d",&q);
        l=1,r=n;
        while (l<r) {
            int mid=l+(r-l)/2;
            if (a[mid]>=q) r=mid; else l=mid+1;
        }
        cout<<a[l];
        
        //查找满足<=q的最后一个数(x或x的前驱) 
        scanf("%d",&q);
        l=1,r=n; 
        while (l<r) {
            int mid=l+(r+1-l)/2;
            if (a[mid]<=q) l=mid; else r=mid-1; 
        }
        cout<<a[l];
        
        return 0;
    } 

    浮点数二分:

    因为不用考虑取整的问题,所以浮点数二分相当好些。

    注意精度问题就可以了。

        double eps=1e-5;
        while (l+eps<r) {
            double mid=(l+r)/2;
            if (check(mid)) l=mid; else r=mid;
        }

    三分求单峰函数极值:

    当这个函数可能是单调函数时(极值点在端点), 三分算法无法到达端点位置, 所以要特判一下两个端点。

    int lm, rm;
    while(l<r) 
    {
        lm = l+(r-l)/2;
        rm = lm+(r-lm)/2;
        if(a[lm] > a[rm]) r = rm;
        else if(a[lm] == a[rm]) r=rm, l=lm;
        else l = lm;
    }
  • 相关阅读:
    原型和原型链的理解
    vue2.0 购物车小球的实现
    canvas 实现规则多边形
    ES6全套教程
    利用canvas实现雪花的飘动
    前端 原型对象中this的认识
    JavaScript——创建对象
    javaScript——原型继承四步曲
    AltiumDesigner使用小窍门 (转)
    C指针理解(转)
  • 原文地址:https://www.cnblogs.com/clno1/p/9681912.html
Copyright © 2011-2022 走看看