这是一道二分查找的模板题,这里先讲一下二分查找
我们以查找3为例,
因为要查找的是序列中第一次出现的编号
因此我们查找的就是分界线(黄色)右边的数字。
蓝色部分我用函数isBlue表示,上代码。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6;
int a[N];
bool isBlue(int num, int x)
{
if (num < x)
{
return true;
}
else
{
return false;
}
}
int binary_serach(int a[], int len, int x)
{
int l = 0, r = len + 1;
while (l + 1 != r)
{
int mid = (l + r) / 2;
if (isBlue(a[mid],x))
{
l = mid;
}
else
{
r = mid;
}
}
if (a[r] == x)
{
return r;
}
else
{
return -1;
}
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m; cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
while (m--)
{
int x;//表示询问这些数字的编号
cin >> x;
int w = binary_serach(a, n, x);
cout << w << " ";
}
return 0;
}
我们要注意l和r的初始化!
因为我们规定初始下标为1因此l=0,r=n+1,n为数组长度
注意:l和r的初始不能在数组下标内
if (a[r] == x)
{
return r;
}
else
{
return -1;
}
由于找的是黄色右边所以是a[r]==x如果是找的黄色的左边则是a[l]==x
代码意义:当黄色右边的数a[r] 等于 需要查找的数字x则 返回r 否则 返回-1
bool isBlue(int num, int x)
{
if (num < x)
{
return true;
}
else
{
return false;
}
}
我们看图,这段代码表示的是蓝色部分
num代表的是a[mid] x为需要查找的数字
由于查找的是黄色右边的数字 所以蓝色部分是num < x
优化:isBlue函数可以不写修改后的代码为
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6;
int a[N];
int binary_serach(int a[], int len, int x)
{
int l = 0, r = len + 1;
while (l + 1 != r)
{
int mid = (l + r) / 2;
if (a[mid] < x)
{
l = mid;
}
else
{
r = mid;
}
}
if (a[r] == x)
{
return r;
}
else
{
return -1;
}
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m; cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
while (m--)
{
int x;//表示询问这些数字的编号
cin >> x;
int w = binary_serach(a, n, x);
cout << w << " ";
}
return 0;
}
可见修改内容为删除了isBlue函数
if(isBlue(a[mid],x))修改为if(a[mid] < x)