C lower_bound的实现

Sha*_*fiz 21 c algorithm binary-search lower-bound

基于此处的以下定义

返回指向排序范围[first,last]中第一个元素的迭代器,它不会比value更小.使用operator <为第一个版本或comp为第二个版本进行比较.

什么是lower_bound()的C等效实现.我知道它将是二进制搜索的修改,但似乎无法确切地指出精确的实现.

int lower_bound(int a[], int lowIndex, int upperIndex, int e);
Run Code Online (Sandbox Code Playgroud)

示例案例:

int a[]= {2,2, 2, 7 };

lower_bound(a, 0, 1,2) would return 0 --> upperIndex is one beyond the last inclusive index as is the case with C++ signature.

lower_bound(a, 0, 2,1) would return 0.

lower_bound(a, 0, 3,6) would return 3;
lower_bound(a, 0, 4,6) would return 3; 
Run Code Online (Sandbox Code Playgroud)

我的尝试代码如下:

int low_bound(int low, int high, int e)
{
    if ( low < 0) return 0;
    if (low>=high )
    {
      if ( e <= a[low] ) return low;
      return low+1;
    }
    int mid=(low+high)/2;
    if ( e> a[mid])
        return low_bound(mid+1,high,e);
    return low_bound(low,mid,e);

}
Run Code Online (Sandbox Code Playgroud)

man*_*h_s 57

以下是相当于实现upper_boundlower_bound.在最坏的情况下,该算法是O(log(n)),与在最坏情况下达到O(n)的接受答案不同.

请注意,此处的high索引设置为n而不是n - 1.这些函数可以返回一个索引,该索引超出了数组的范围.即,如果找不到搜索关键字,它将返回数组的大小,并且它大于所有数组元素.

int bs_upper_bound(int a[], int n, int x) {
    int l = 0;
    int h = n; // Not n - 1
    while (l < h) {
        int mid = (l + h) / 2;
        if (x >= a[mid]) {
            l = mid + 1;
        } else {
            h = mid;
        }
    }
    return l;
}

int bs_lower_bound(int a[], int n, int x) {
    int l = 0;
    int h = n; // Not n - 1
    while (l < h) {
        int mid = (l + h) / 2;
        if (x <= a[mid]) {
            h = mid;
        } else {
            l = mid + 1;
        }
    }
    return l;
}
Run Code Online (Sandbox Code Playgroud)

实际的C++实现适用于所有容器.你可以在这里找到它.

  • 最好用l +(h - l)/ 2替换表达式:(l + h)/ 2以防止潜在溢出. (8认同)
  • @ShivamDixit考虑到32位整数,你需要超过2 ^ 30,即数组中的1073741824元素才能接近该溢出.考虑4字节整数数组,存储数组需要4 GB或以上的RAM.在这里保持解决方案简单.这足以满足所有在线竞争性编程问题. (3认同)

Chr*_*ung 10

lower_bound 几乎就像做一般的二分搜索,除了:

  1. 如果找不到该元素,则在搜索中返回当前位置,而不是返回一些空值.
  2. 如果找到该元素,则向左搜索,直到找到不匹配的元素.然后将指针/迭代器返回到第一个匹配元素.

是的,它真的那么简单.:-)

  • 虽然要注意`upper_bound`**也就像执行"常规"二进制搜索一样,但是如果找不到该元素,则会在搜索中返回当前位置.还有一个微妙的区别:-).同样在这两种情况下,如果找到元素你不能只停止,你必须继续检查.基本上`lower_bound`是一个二进制搜索,寻找指定的"间隙",左边的元素较小,右边的元素较小.然后将迭代器返回到该间隙右侧的元素.常规二进制搜索正在寻找一个元素,而不是"差距", (9认同)
  • 请注意,向左搜索必须是二分搜索,而不是线性搜索.否则,您可能违反性能约束. (5认同)
  • 而实际上你并没有那样实现,"首先找到匹配,然后找到不匹配".你做了cplusplus.com上的代码所做的事情,即搜索你正在寻找的不连续性,在较小元素和非较小元素之间.然后在`upper_bound`中搜索不大元素和更大元素之间的不连续性."常规"二进制搜索可以多种方式编写 - 如果元素丢失,其中一个最终会在下限处结束,另一个最终会在上限处结束.我认为,这取决于您将所寻求的元素放在比较的哪一方. (3认同)