这里针对数组中有多个重复元素对二分查找法进行了如下的改进
floor函数:在arr中寻找target,如果存在,则返回target的最小索引,如果不存在,则返回比target小的那个值的最大索引 ,如果target比arr中最小的元素都还要小,则说明target不在数组arr中,则返回-1
ceil函数:/在arr中寻找target,如果存在,则返回target的最大索引,如果不存在,则返回比target大的那个值的最小索引,如果target比arr中比最大的元素都还要大,则说明target不在数组arr中,则返回-1
顺便推荐一个课程,我最近的算法学习都是从这个课程上学来的,包括这个的代码啊,也是仿照着bobo老师的代码后写出来的
https://coding.imooc.com/class/71.html
#include<iostream>
#include<cassert>
#include<ctime>
using namespace std;
//在arr中寻找target,如果存在,则返回target的最小索引,如果不存在,则返回比target小的那个值的最大索引
//如果target比arr中最小的元素都还要小,则说明target不在数组arr中,则返回-1
template<typename T>
int floor(T arr[], int n, T target)
{
assert( n >= 0); //这一个忘记了
int l,r;
l = -1; r = n-1; //如果这里是l = 0的话,就会找到的第一个值是1
if(target < arr[l+1])
return -1;
while(l < r)
{
int mid = l + (r-l+1)/2;
if(arr[mid] >= target)
r = mid-1;
else
l = mid;
}
assert(l == r);
if( l + 1 < n && arr[l+1] == target)
return l + 1;
return l;
}
//在arr中寻找target,如果存在,则返回target的最大索引,如果不存在,则返回比target大的那个值的最小索引
//如果target比arr中比最大的元素都还要大,则说明target不在数组arr中,则返回-1
template<typename T>
int ceil(T arr[],int n, T target)
{
assert(n >= 0);
int l,r;
l = 0; r = n;
if(arr[r-1] < target)
return -1;
// 寻找比target大的最小索引值
while(l < r)
{
int mid = l + (r-l)/2; //这里是 l-r
if(arr[mid] > target) //这里不能 >=
r = mid;
else
l = mid + 1;
}
assert(l == r);
if(r - 1 >= 0 && arr[r-1] == target)
return r-1;
return r;
}
int main(int argc, char const *argv[])
{
//int *arr = new int[10];
int a[] = {1, 1, 1, 2, 2, 2, 2, 2, 4, 4, 5, 5, 5, 6, 6, 6};
int n = sizeof(a) / sizeof(int);
for(int i = 0; i <= 8; i++)
{
int floorIndex = floor(a,n,i);
cout << "the floor index of " << i << " is " << floorIndex << ".";
cout << endl;
if(floorIndex >= 0 && floorIndex < n)
cout << "The value is " << a[floorIndex] << ".";
cout << endl;
int ceilIndex = ceil(a,sizeof(a)/sizeof(int),i);
cout << "the ceil index of " << i << " is " << ceilIndex << ".";
cout << endl;
if(ceilIndex >= 0 && ceilIndex < n)
cout << "The value is " << a[ceilIndex] << ".";
cout << endl;
cout << endl;
}
return 0;
}