系统会为您提供一组数字,然后是数字 查询,对于每个查询,如果查询的数字存在于数组中 打印其位置,否则打印-1。
输入
第一行包含N Q,数组中的元素数和 要跟踪的查询
第二行包含N个数字,数组元素,每个数字 将是-10 ^ 9 <= ai <= 10 ^ 9,0
参考:https://www.spoj.com/problems/BSEARCH1/
我的代码在终端上工作正常,但是即使花费O(NQ)时间,也超出了在线裁判的时间限制。
这是我的代码:
#include <iostream>
long long binarySearch(long long arr[], long long l , long long r , long long x) {
long long mid;
if (r >= l){
mid = (l+r)/2;
if (arr[mid] == x) {
if (arr[mid] == arr[mid-1]) {
while (arr[mid] == arr[mid-1]) {
--mid;
}
return mid;
}
else{
return mid;
}
}
if (arr[mid] > x) {
return binarySearch(arr,l,mid-1,x);
}
if (arr[mid] < x) {
return binarySearch(arr,mid+1,r,x);
}
}
return -1;
}
int main() {
long long n ,q;
std::cin >> n >> q;
long long array[n];
for (long long i = 0; i < n; ++i) {
std::cin >> array[i];
}
long long x;
long long arr2[q];
for (long long i = 0 ; i < q ; ++i) {
std::cin >> x;
std::cout << binarySearch(array,0,n-1,x) << "\n";
}
return 0;
}
答案 0 :(得分:0)
我认为您要尝试的是打印找到的元素的第一个位置。但是,如果您有一个所有元素都相同的1,1,1,1,1,1,1
数组,则基本上是对一个查询执行O(n)
,这将导致O(nq)
,其中n是数组的长度,q是最坏情况下的查询数量。
建议: 我认为您需要做的是消除重复项。
std::vector<std::pair<int,int>
。以(element,first-pos)作为对。答案 1 :(得分:0)
我认为主要问题是您对二进制搜索的实现是递归。
我不知道本地输入数据是否很大以测试您的实现是否合适。但是,如果将this example这样的递归实现更改为迭代,则代码的性能将得到增强。
迭代实现优于递归的原因,请检查this。
请注意,使用具有尾调用优化功能的编译器,可以消除递归实现速度的降低。
答案 2 :(得分:0)
您不需要重新发明轮子。您可以使用C ++标准库算法std::lower_bound
。它会对该值可能位于的第一个位置进行二进制搜索。
您可以按以下方式重写函数:
#include <algorithm>
long long binarySearch(long long arr[], long long n, long long x)
{
// O(log n) binary search for first element not less that x
long long *itr = std::lower_bound(arr, arr + n, x);
// If itr is array end or location doesn't contain x
if (itr == arr + n || *itr != x) {
return -1;
}
// Compute index by address arithmetic
return itr - arr;
}
我删除了一个不必要的函数参数,只需传递数组大小即可。顺便说一句,您不需要long long
来解决此问题。最好使用int
并节省一些内存。
如果仍然存在超时问题,则可能是输入/输出速度很慢。尝试在main()
的开头添加下两行。
std::ios_base::sync_with_stdio(false); // possibly faster I/O buffering
std::cin.tie(NULL); // don't flush output stream before doing input