zoukankan      html  css  js  c++  java
  • 二分查找

    有一位长者说过: 手写二分是基本的素养。 还有一位长者说过: 写二分要从娃娃抓起。

    如果想快速手写二分,首先要明确搜索区间的表示。 有的人喜欢用[], 我是[) 即前闭后开区间的支持者。要避免在使用中出错,应该固定使用一种区间表示。

    版本1

    按照定义直接来的二分查找,就是当查找中点定位到要查找的值时直接返回的查找。 这种查找版本实际上是一个“三分”查找,因为每一轮运行都把区间[lo, hi)分为了三部分[lo, mi), [mi], [mi+1, hi)

    为了简便,这里用vector<int>做例子。

    int binSearch(vector<int> &A, int tar, int lo, int hi) {
        while(lo < hi) {
            int mi = lo + (hi - lo >> 1);
            if      (tar < A[mi]) hi = mi;
            else if (A[mi] < tar) lo = mi + 1; 
            else                  return mi;
        }
        return -1;
    }
    
    

    版本2

    二分查找有时候有一些特殊的要求, 比如我们要讨论的要求返回数组中第一个等于tar的元素。 我们就需要对版本1做一点修改。要注意,我们使用使用[) 前闭后开的区间表示方式。

    这个版本的思想实际上是让[lo, hi)中的lo在循环中始终指向第一个大于等于tar的元素。

    int binSearch(vector<int> &A, int tar, int lo, int hi) {
        while (lo < hi) {
            int mi = lo + (hi - lo >> 1);
            if (A[mi] < tar) lo = mi + 1;
            else             hi = mi; 
        }
        return lo;
    }
    

    这个版本不像版本1一样在查找失败的时候可以返回-1, 所以调用这个函数需要自己做好后续处理。

    版本3

    接着上面的版本2, 如果我们想要找到数组中最后一个等于tar的元素呢? 之前我们是在lo指向的元素身上做文章,这次我们就在hi指向的元素身上做文章。 让hi一直指向第一个大于tar的元素。

    注意: 不要改变[)的区间表示。

    int binSearch(vector<int>& A, int tar, int lo, int hi) {
        while (lo < hi) {
            int mi = lo + (hi - lo >> 1);
            if (A[mi] > tar) hi = mi;
            else             lo  = mi + 1;
        }
        return hi - 1;
    }
    

    同样, 这个版本不像版本1一样在查找失败的时候可以返回-1, 所以调用这个函数需要自己做好后续处理。

    通过 版本2版本3 就可以获得一个目标值的闭区间。

  • 相关阅读:
    数据库路由中间件MyCat
    数据库路由中间件MyCat
    数据库路由中间件MyCat
    数据库路由中间件MyCat
    数据库路由中间件MyCat
    数据库路由中间件MyCat
    数据库路由中间件MyCat
    云架构师进阶攻略(3)
    PAT 1059. C语言竞赛
    PAT 1058. 选择题
  • 原文地址:https://www.cnblogs.com/whensean/p/binary_search.html
Copyright © 2011-2022 走看看