经典算法 ——二分(找出指定数在数组中的范围)
链接:https://www.nowcoder.com/questionTerminal/3783c394c5d84d5ab9e55d91a6efeb8c?answerType=1&f=discussion
来源:牛客网
输入一个排好序的整数数组,找到指定目标数的开始和结束位置。如果指定的数字不在数组中,则输出 [-1,-1]。例如,输入数组为[5, 7, 7, 8, 8, 10], 目标数为8, 输出[3, 4].本题会人工判题,要求时间复杂度O(logn)
输入描述:
输入数据包括两行:
第一行两个整数n(1 ≤ n ≤ 10 ^ 5),和需要查找的数target
第二行n个整数,范围均在32位整数内,以空格分隔
输出描述:
输出格式为[begin,end],如果不存在就输出[-1,-1]
示例1
输入
6 8 5 7 7 8 8 10
输出
3 4
#include<iostream>
using namespace std;
int a[100010];//创建一个数组
int n;//数组中共有n个数
int target;//指定数
int main()
{
cin>>n>>target;//输入n和指定数的值
for(int i=0;i<n;i++) scanf("%d",&a[i]);//输入数组中的数
int l=0,r=n-1;//数组的两个边界的下标
while(l<r)
{
int mid=l+r>>1;//数组中间的下标
if(a[mid]>=target) r=mid;//如果a[mid]在target的右侧,则改变数组的右边界
else l=mid+1;//反之则改变数组的左边界
}
if(a[l]!=target)cout<<"[-1,-1]"<<endl;//l下标的数应是target,如果不是,那么在这个数组中就没有这个数
else
{
cout<<"["<<l;//输出l的值,l是范围的最左侧的下标
int l=0,r=n-1;
while(l<r)
{
int mid=l+r+1>>1;//为什么和第一次相比加了一个1呢?这是因为如果这个数组只有两个数的话,将会出现死循环,这其实是由后面的if语句造成的,如果a[mid]=target的时候l=mid,那么就是这个地方要加一了
if(a[mid]<=target) l=mid;//原因同上一次
else r=mid-1;//原因同上一次
}
cout<<l<<"]"<<endl;//输出范围的最右端
}
return 0;
}