携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情
【深基13.例1】查找
题目描述
输入 个不超过 的单调不减的(就是后面的数字不小于前面的数字)非负整数 ,然后进行 次询问。对于每次询问,给出一个整数 ,要求输出这个数字在序列中第一次出现的编号,如果没有找到的话输出 -1 。
输入格式
第一行 2 个整数 n 和 m,表示数字个数和询问次数。
第二行 n 个整数,表示这些待查询的数字。
第三行 m 个整数,表示询问这些数字的编号,从 1 开始编号。
输出格式
m 个整数表示答案。
样例 #1
样例输入 #1
11 3
1 3 3 3 5 7 9 11 13 15 15
1 3 6
样例输出 #1
1 2 -1
提示
规模的数据读入,请用 scanf。用 cin 会超时。
思路
这里需要注意,在二分的过程中要寻找到一个确定数,未找到则返回-1 因为外层while循环条件为lo < hi,如果lo == hi则跳出循环 此外查找的数必须是第一次出现的位置,因此如果mid合法,就需要向左收缩区间,即hi = mid 这两点考虑清楚二分的函数就很好写了
代码
// P2249 【深基13.例1】查找
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[1000010];
int q[100010];
int search_binary(int key, int a[], int lo, int hi){
//key为查找数,a为查找数组,lo-hi为查找区间下标
//返回key在a数组的[lo,hi]区间中第一次出现的下标值+1(即位置),未查找到则返回-1
while(lo < hi){//当hi == lo时跳出
int mid = (hi- lo)/2 + lo;
if (key < a[mid]) hi = mid-1; //向左收缩区间
else if (key > a[mid]) lo = mid+1; //向右收缩区间
else hi = mid; //向左收缩区间,但保留当前数
}
if(a[hi] == key) return hi+1;
else return -1;
}
int main(){
int n, m;
cin >> n >> m;
for(int i=0; i<n; i++){
scanf("%d", &a[i]);
}
for(int i=0; i<m; i++){
scanf("%d", &q[i]);
cout << search_binary(q[i], a, 0, n-1) << " ";
}
return 0;
}