zoukankan      html  css  js  c++  java
  • 二分搜索的写法

    二分搜索框架

    int L,R,key;
    while(L<=R)
    {
        int mid=(L+R)>>1;
        if(a[mid]<key or a[mid]<=key)
            L=mid+1;
        else
            R=mid-1;
    }
    return L or R;
    

    问题

    二分搜索大家都很熟悉。如果待查区间内只有一个key值,要求找出key,那么一切都很容易。

    但是如果有多个key,或者没有key,在不依赖现有库函数的情况下,怎么做到返回第一个key的位置,或最后一个key的位置,或者第一个大于key的位置此类的要求呢?

    解决

    其实很简单,只需要关注两个部分,一个是比较,另一个是返回值。

    比较的控制

    1. 假设区间内有key,那么a[mid]<=key的写法会使得左端点一直向右移动。这样当L==R时,找到的就是最后一个key的位置。

      同理,a[mid]<key的写法会使得右端点向左移动,当L==R时,找到的就是第一个key的位置。

    2. 若区间内没有key,那么两种写法是等价的,因为不存在a[mid]==key的情况。

    返回值的问题

    ​ 注意到,二分搜索结束的条件是L>R,那么最后的状态一定是LR的右边,二者相邻。

    1. 如果有key,那么根据上文中所述的写法的不同,会有两种情况。

      1.1 R指向最后一个keyLR右侧。

      1.2 L指向第一个keyRL左侧。

    2. 如果没有key。那么只有一种情况,即L指向第一个大于key的元素,R指向最后一个小于key的元素。

    至此问题就解决了,只需要控制这两部分,就可以实现任意一种二分搜索的变体。

    示例

    1. 查找第一个大于key的元素位置(类似stl的upper_bound的功能)

      int L,R,key;
      while(L<=R)
      {
          int mid=(L+R)>>1;
          if(a[mid]<=key)
              L=mid+1;
          else
              R=mid-1;
      }
      return L;
      
    2. 查找第一个key的位置,若不存在,则返回第一个大于key的元素位置(类似stl的lower_bound的功能)

      int L,R,key;
      while(L<=R)
      {
          int mid=(L+R)>>1;
          if(a[mid]<key)
              L=mid+1;
          else
              R=mid-1;
      }
      return L;
      
    3. 查找最后一个小于等于key的元素的位置

      int L,R,key;
      while(L<=R)
      {
          int mid=(L+R)>>1;
          if(a[mid]<=key)
              L=mid+1;
          else
              R=mid-1;
      }
      return R;
      
  • 相关阅读:
    常见sql注入的类型
    sql-labs 18-20(sqlmap注入)
    sqli-labs11-17(手注+sqlmap)
    Android Zygote进程启动分析
    android点击桌面App图标activity启动流程
    Android启动过程
    android主线程ActivityThread
    mac上写c++
    Gradle发布项目到 maven 之novoda/bintray-release(3)
    Gradle发布项目到 maven 之gradle-bintray-plugin(2)
  • 原文地址:https://www.cnblogs.com/cryingrain/p/14920668.html
Copyright © 2011-2022 走看看