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 就可以获得一个目标值的闭区间。

  • 相关阅读:
    jvm基本结构和解析
    多态的意思
    java中对象的简单解读
    double类型和int类型的区别
    python 解析xml文件
    win10不能映射Ubuntu共享文件
    Qt程序打包
    Ubuntu boot分区文件误删,系统无法启动,怎么解
    ubuntu Boot空间不够问题“The volume boot has only 5.1MB disk space remaining”
    Ubuntu 分辨率更改 xrandr Failed to get size of gamma for output default
  • 原文地址:https://www.cnblogs.com/whensean/p/binary_search.html
Copyright © 2011-2022 走看看