题目描述:
给定一个按照升序排列的长度为 n 的整数数组,以及 q 个查询。
对于每个查询,返回一个元素 k 的起始位置和终止位置(位置从 0 开始计数)。
如果数组中不存在该元素,则返回 -1 -1。
输入格式:
第一行包含整数 n 和 q,表示数组长度和询问个数。
第二行包含 n 个整数(均在 1∼10000 范围内),表示完整数组。
接下来 q 行,每行包含一个整数 k,表示一个询问元素。
输出格式:
共 q 行,每行包含两个整数,表示所求元素的起始位置和终止位置。
如果数组中不存在该元素,则返回 -1 -1。
解题思路: 这一题考察的是二分查找。要查找的数的范围涉及到二分查找的左值下标和右值下标。二分查找的关键在与判断条件的取舍,这点非常重要。请看代码:
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
const int N = 100000;
int n, m;
int a[N];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
while (m--)
{
int x = 0;
cin >> x;
int left = 0;
int right = n - 1;
while (left < right)
{
//二分查找获得左值下标
int mid = left + right >> 1;
if (a[mid] >= x)
right = mid;
else
left = mid + 1;
}
if (a[left] != x)
cout << "-1"
<< " -1" << endl;
else
{
cout << left << " ";
left = 0;
right = n - 1;
while (left < right)
{
//二分查找获得右值下标
int mid = left + right + 1 >> 1;
if (x >= a[mid])
left = mid;
else
right = mid - 1;
}
cout << right << endl;
}
}
return 0;
}
左值查找:
int binaryLeft(int *a, int length, int target)
{
int left = 0;
int right = length - 1;
while (left < right)
{
int mid = left + right >> 1;
if (a[mid] >= target)
{
right = mid;
}
else
{
left = mid + 1;
}
}
if (a[left] != target)
return -1;
return left;
}
右值查找:
int binaryRight(int *a, int length, int target)
{
int left = 0;
int right = length - 1;
while (left < right)
{
int mid = left + right + 1 >> 1;
if (a[mid] > target)
{
right = mid - 1;
}
else
{
left = mid;
}
}
if (a[left] != target)
return -1;
return left;
}