基于以下定义here
返回指向。的迭代器 排序范围中的第一个元素 [第一个,最后一个]没有比较 低于价值。比较是 使用任一运算符<为了 第一个版本,或第二个版本。
lower_bound()的C等效实现是什么。我知道这将是对二进制搜索的修改,但似乎无法完全确定实现。
int lower_bound(int a[], int lowIndex, int upperIndex, int e);
示例案例:
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;
我的尝试代码如下:
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);
}
答案 0 :(得分:47)
以下是upper_bound
和lower_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;
}
实际的C ++实现适用于所有容器。你可以找到它here。
答案 1 :(得分:9)
lower_bound
几乎就像进行常规的二分搜索一样,除了:
是的,真的那么简单。 : - )
答案 2 :(得分:2)
python中的lower_bound
和upper_bound
函数将按如下方式实现:
def binLowerBound(a, lo, hi, x):
if (lo > hi):
return hi
mid = (lo + hi) / 2;
if (a[mid] == x):
return binLowerBound(a, lo, mid-1, x)
elif (a[mid] > x):
return binLowerBound(a, lo, mid-1, x)
else:
return binLowerBound(a, mid+1, hi, x)
def binHigherBound(a, lo, hi, x):
if (lo > hi):
return lo
mid = (lo + hi) / 2;
if (a[mid] == x):
return binHigherBound(a, mid+1, hi, x)
elif (a[mid] > x):
return binHigherBound(a, lo, mid-1, x)
else:
return binHigherBound(a, mid+1, hi, x)
答案 3 :(得分:1)
我知道这是一篇非常古老的帖子。但是,我正在解决一个问题,我遇到了这个帖子。我想为问题添加我的迭代版本,这是最后一个答案的扩展。我用我能想到的测试用例检查了这一点。我已将代码附加在C#中。
此代码适用于所有范围。但是,范围应该在最后一个索引的第一个索引+ 1之内。如果数组的大小为N且考虑范围为[0,N],则搜索空间将在[0,N]内。我知道这很明显,但它帮助我检查了一些边缘情况。
static int lower_bound(int[] a, int lo,int hi, int x)
{
while (lo < hi)
{
int mid = lo + (hi-lo) / 2;
if(a[mid]==x)
{
/*when there is a match, we should keep on searching
for the next same element. If the same element is not
found, mid is considered as the answer and added to 'hi'
Finally 'hi' is returned*/
if(a[mid-1]!=x)
{
hi=mid;
break;
}
else
hi=mid-1;
}
else if(a[mid]>x)
hi=mid-1;
else
lo=mid+1;
}
//if element is not found, -1 will be returned
if(a[hi]!=x)
return -1;
return hi;
}
static int upper_bound(int[] a, int lo,int hi, int x)
{
int temp=hi;
while (lo < hi)
{
int mid = lo + (hi-lo) / 2;
if(a[mid]==x)
{
/*this section make sure that program runs within
range [start,end)*/
if(mid+1==hi)
{
lo=mid;
break;
}
/*when there is a match, we should keep on searching
for the next same element. If the same element is not
found, mid is considered as the answer and added to
'lo'. Finally 'lo' is returned*/
if(a[mid+1]!=x)
{
lo=mid;
break;
}
else
lo=mid+1;
}
else if(a[mid]>x)
hi=mid-1;
else
lo=mid+1;
}
//if element is not found, -1 will be returned
if(a[lo]!=x)
return -1;
return lo;
}
以下是我使用的测试用例:
Array(a) : 1 2 2 2 2 5 5 5 5
size of the array(a) : 9
将搜索元素视为2:
upper_bound(a,0,9,2)=4, lower_bound(a,0,9,2)=1
将搜索元素视为5:
upper_bound(a,0,9,2)=8, lower_bound(a,0,9,2)=5
将搜索元素视为1:
upper_bound(a,0,9,2)=0, lower_bound(a,0,9,2)=0
将搜索元素视为5:
upper_bound(a,5,9,2)=8, lower_bound(a,5,9,2)=5
答案 4 :(得分:0)
int lowerBound (int *a, int size, int val) {
int lo = 0, hi = size - 1;
while (lo < hi) {
int mid = lo + (hi - lo)/2;
if (a[mid] < val)
lo = mid + 1;
else
hi = mid;
}
return lo;
}
答案 5 :(得分:0)
C ++实现
int binary_search_lower_bound(vector<int>& array, int target) {
int lo = 0, hi = (int)array.size();
int mid;
while(lo < hi) {
mid = lo + ((hi - lo) >> 1);
int val = array[mid];
if (target <= val)//array[mid])
hi = mid;
else
lo = mid + 1;
}
return lo;
}
编辑:修复了不存在的值的错误。
答案 6 :(得分:0)
如果这是给定数组,则为示例
1 2 3 3 4
x的不同值为
3,则firstOccurance将为2,lastOccurance将为3
2,则firstOccurance将为1,lastOccurance将为1
10,则firstOccurance将为-1,lastOccurance将为-1
int firstOccurance(vector<int>& arr, int x){
int low = 0;
int high = arr.size();
int ans=-1;
while(low<=high){
int mid = (low+high)/2;
if(arr[mid]==x) ans=mid;
if(arr[mid]>=x) high=mid-1;
else low = mid+1;
}
return ans;
}
int lastOccurance(vector<int>& arr, int x){
int low = 0;
int high = arr.size();
int ans=-1;
while(low<=high){
int mid = (low+high)/2;
if(arr[mid]==x) ans=mid;
if(arr[mid]<=x) low=mid+1;
else high = mid-1;
}
return ans;
}
答案 7 :(得分:0)
我知道这是一篇非常老的文章,已经给出了很多答案,但是我也遇到了这个问题,并且需要通用的解决方案,因此我使用了manish_s答案来适应gnu stdlib bsearch函数。如果有人需要它:
size_t myBsearch (const void *__key, const void *__base, size_t __nmemb, size_t __size,
__compar_fn_t __compar)
{
size_t __l, __u, __idx;
const void *__p;
int __comparison;
__l = 0;
__u = __nmemb;
while (__l < __u)
{
__idx = (__l + __u) / 2;
__p = (void *)(((const char *)__base) + (__idx * __size));
__comparison = (*__compar)(__key, __p);
if (__comparison <= 0)
__u = __idx;
else if (__comparison > 0)
__l = __idx + 1;
}
return __l;
}