先贴个题目:
以及原题链接:789. 数的范围 - AcWing题库https://www.acwing.com/problem/content/791/ 然后先讲讲读题思路,这题一看就是经典中的经典,整数二分,只不过多了一个范围而已,那其实也就多了一次二分查找罢了,一次左端点一次右端点,经典二分,结束。
附代码:
#include <iostream>
using namespace std;
int main()
{
int n, q;
cin >> n >> q;
int *a = new int[n + 10];
for (int i = 0; i < n; ++i)
scanf("%d", &a[i]);
int num, left, right, mid, x, y;
for (int ii = 0; ii < q; ++ii)
{
left = 0;
right = n - 1;
scanf("%d", &num);
while (left < right)
{
mid = (left + right) / 2;
if (a[mid] >= num)
right = mid;
else
left = mid + 1;
}
if (a[left] != num)
{
cout << "-1 -1" << endl;
continue;
}
x = left;
right = n - 1;
while (left < right)
{
mid = (left + right+1) / 2;
if (a[mid] > num)
right = mid - 1;
else
left = mid;
}
y = left;
cout << x << " " << y << endl;
}
return 0;
}
总结下这题代码要注意的点,可以看到两次二分的中点的计算是有区别的:
mid = (left + right) / 2;
mid = (left + right+1) / 2;
原因很简单,第一次查找的是二分后的左端点,第二次是右端点,为了避免死循环,所以一个向下取整一个向上取整,验证方法很简单,当left=right-1即只有两个数的情况时,判断会不会产生死循环即可。其他的话没什么难点。
by————2024.1.30刷题记录