说明
请在一个有序不递减的数组中(数组中的值有相等的值),采用二分查找,找到最后1次出现值x的位置,如果不存在x请输出-1。
请注意:本题要求出q个x,每个x在数组中最后一次出现的位置。
比如有6个数,分别是:1 2 2 2 3 3,那么如果要求3个数:3 2 5,在数组中最后一次出现的位置,答案是:6 4 -1。
输入格式
第一行,一个整数n,代表数组元素个数(n <= 105)
第二行,n个整数,用空格隔开,代表数组的n个元素(1<=数组元素的值<=108)
第三行,一个整数q,代表有要求出q个数最后一次出现的位置(q<=105)
第四行,q个整数,用空格隔开,代表要找的数(1<=要找的数<=108)
输出格式
按题意输出位置或者-1。
样例
输入数据 1
6
1 2 2 2 3 3
3
3 2 5
Copy
输出数据 1
6 4 -1
题解
首先把上面二分查找左侧边界的答案搬下来:
#include <bits/stdc++.h>
using namespace std;
int l, r, x, a[100001], n, ans, q;
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
cin >> q;
for (int i = 1; i <= q; i++)
{
cin >> x;
ans = -1;
l = 1;
r = n;
while (l <= r)
{
int mid = (l + r) / 2;
if (a[mid] >= x)
{
if (a[mid] == x)
{
ans = mid;
}
r = mid - 1;
}
else
{
l = mid + 1;
}
}
cout << ans <<" ";
}
return 0;
}
Copy
然后把
r = mid - 1;
Copy
和
l = mid + 1
Copy
的位置交换一下:
#include <bits/stdc++.h>
using namespace std;
int l, r, x, a[100001], n, ans, q;
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
cin >> q;
for (int i = 1; i <= q; i++)
{
cin >> x;
ans = -1;
l = 1;
r = n;
while (l <= r)
{
int mid = (l + r) / 2;
if (a[mid] <= x)
{
if (a[mid] == x)
{
ans = mid;
}
l = mid + 1;
}
else
{
r = mid - 1;
}
}
cout << ans <<" ";
}
return 0;
}
Copy
再来看一下ChatGPT的解释和注意事项(废话有亿点多):
这段代码实现了二分查找的功能。
它首先输入了一个整数 n,然后输入了 n 个数存储在数组 a 中。接着输入了另一个整数 q,表示要进行的查询次数。接下来,对于每一次查询,它会输入一个数 x,并在数组 a 中查找是否有数与 x 相等。
为了实现二分查找,它使用了一个循环来进行多次查询。在每次查询中,它首先将查询范围的左端点设为 l,右端点设为 r,然后不断地更新这两个变量,直到找到等于 x 的数或者查询范围为空。
具体地,每次循环中,它都会计算出查询范围的中点 mid,然后比较 a[mid] 与 x 的大小关系。如果 a[mid] 小于等于 x,那么它就更新左端点 l 为 mid+1,继续查找。如果 a[mid] 大于 x,那么它就更新右端点 r 为 mid-1,继续查找。如果在某次查找中发现 a[mid] 等于 x,那么它就将答案设为 mid,并继续查找。
当循环结束时,如果答案仍然是 -1,说明数组中不存在数与 x 相等;如果答案不是 -1,说明数组中存在数与 x 相等,且答案为这个数在数组中的下标。最后,它会将答案输出到控制台。
代码中包含了两个头文件:
#include <bits/stdc++.h>:这个头文件包含了许多常用的 C++ 标准库头文件,包括 iostream、string、algorithm 等。
using namespace std;:这句话告诉编译器使用标准 C++ 库中的命名空间 std。
代码中定义了四个变量:
l、r:表示查询范围的左端点和右端点。
x:表示当前查询的数。
a:表示存储了 n 个数的数组。
ans:表示查询结果,如果查找到数与 x 相等,则为这个数在数组中的下标;否则为 -1。
代码中包含了两个循环:
外层循环:用于控制进行的查询次数。
内层循环:用于控制查找的过程,每次查找都会更新查询范围的左右端点。
最后,代码中的 return 0; 表示程序执行结束,并返回 0。
代码中的几个函数和操作值得注意:
cin 和 cout:分别表示输入和输出流,用于读入和输出数据。
>> 和 <<:分别表示流提取和流插入运算符,用于从输入流读入数据或者向输出流输出数据。
while 循环:当某个条件为真时,不断执行循环体中的语句。
/ 运算符:表示除法运算,用于计算查询范围的中点。
if 语句:如果某个条件为真,则执行语句块中的语句;否则执行其他语句。
希望这些解释能够帮助你理解代码的意义。如果你对二分查找或者 C++ 中的其他知识点