问题描述:
写一个函数 BinarySeach,在包含 size 个元素的、从小到大排序的 int 数组 a 里查找元素 p,如果找到,则返回元素下标,如果找不到,则返回-1。要求复杂度 O(log(n))
代码:
#include<iostream>
using namespace std;
int BinarySeach(int a[], int size,int p)
{
int left = 0; //查找区间的左端点
int right = size - 1; //查找区间的右端点
int mid;
while (left<=right) //如果查找区间不为空,继续查找(小于等于)
{
mid = left + (right - left) / 2; //取查找区间正中元素的下标
if (p == a[mid])
return mid;
if (p > a[mid])
left = mid + 1; //设置新的查找区间的左端点
else
right = mid - 1; //设置新的查找区间的右端点
}
return -1; //找不到
}
int main()
{
int a[] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
int len = sizeof(a) / sizeof(a[0]);
cout << BinarySeach(a, len, 8)<<endl;
return 0;
}
我学到的:
问题描述:
写一个函数 LowerBound,在包含 size 个元素的、从小到大排序的 int 数组 a 里查找比给定整数 p 小的,下标最大的元素。找到则返回其下标,找不到则返回-1
代码:
#include<iostream>
using namespace std;
int LowerBound(int a[], int size, int p)
{
int left = 0; //查找区间的左端点
int right = size - 1; //查找区间的右端点
int mid,lastpos=-1; //lastpos为到目前为止找到的最优解
while (left<=right) //如果查找区间不为空,继续查找(小于等于)
{
mid = left + (right - left) / 2; //取查找区间正中元素的下标
if (a[mid]>=p) //题目是找小于 p的整数,故是小于等于
right = mid - 1;
else
{
lastpos = mid; //记录当前最优解
left = mid + 1;
}
}
return lastpos;
}
int main()
{
int a[] = { 1,2,3,4,5,6,7,8,9,10,11,12};
int len = sizeof(a) / sizeof(a[0]);
cout << LowerBound(a, len, 8) << endl;
return 0;
}
我学到的:
此题,看到数组是从小到大排列的,就应该想到二分法。每次将数组分一半,如果中间元素大于等于 p,继续在左侧区间寻找,如果中间元素小于p,记录这个位置,继续在右侧区间寻找。当区间长度变为0时,该位置就是 p 左侧的第一个元素(即下标最大的元素)
有一个细节需要注意:在取中间元素的时候,最好使用 int mid = L+(R-L)/2; 如果使用 int mid = (L+R)/2; 在计算 (L+R) 时可能结果过大,超过了 int 的表示范围,溢出了