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;
      
  • 相关阅读:
    LeetCode(287)Find the Duplicate Number
    LeetCode(290) Word Pattern
    LeetCode(205)Isomorphic Strings
    LeetCode(201) Bitwise AND of Numbers Range
    LeetCode(200) Number of Islands
    LeetCode(220) Contains Duplicate III
    LeetCode(219) Contains Duplicate II
    命令行执行Qt程序
    LeetCode(228) Summary Ranges
    redis 的安装和使用记录
  • 原文地址:https://www.cnblogs.com/cryingrain/p/14920668.html
Copyright © 2011-2022 走看看