我给了一个数字说N和它在数组中的相应位置。 说给出的位置(指数)是:
4 5 8 11 13 15 21 28
我给了两个位置(指数)说x和y。设x = 7,y = 13。
我需要找到x和y之间有多少次出现的数字(两者都包括在内,y> = x)。与上面的例子一样,数字存在于位置x和y之间的位置8,11和13处,因此答案是3。
一个简单的方法是天真的O(n)算法,但我想利用这样的事实,即poistions总是按升序给出。我认为以修改的方式应用二进制搜索可能有所帮助,但我面临着麻烦。
// P is the array that stores positions(indices) of number
int start=0,End=n-1; // n is the size of array P
int mid=(start+End)/2;
int pos1=0,pos2=0;
while(End>start)
{
mid=(start+End)/2;
if(P[mid]>=x && P[mid-1]<x && flag1!=0)
{
pos1=mid;
flag1=0
}
if(P[mid]<=y && P[mid+1]>y && flag2!=0)
{
pos2=mid;
flag2=0;
}
else if (P[mid]<x)
start=mid;
else
End=mid;
}
int Number_Of_Occurence=(pos2-pos1);
您能否建议我的代码可能出错?
答案 0 :(得分:5)
您可以利用STL库。想到std::lower_bound
或std::upper_bound
。
对于具有随机迭代器的已排序容器,两者都具有对数复杂度。
例如:
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> v = {4, 5, 7, 8, 11, 13, 15, 21, 28};
int low_value = 7;
int high_value = 13;
auto low = std::lower_bound(v.begin(), v.end(), low_value);
auto high = std::upper_bound(v.begin(), v.end(), high_value);
std::cout << std::distance(low, high) << " elements in interval ["
<< low_value << ", " << high_value << "]" << std::endl;
return 0;
}
答案 1 :(得分:1)
我大胆地假设这不是一个家庭作业问题......你需要找到两个端点的索引,但是你的代码只有一个&#34; mid&#34;变量。假设您正确地重新实现了两个端点的二进制搜索并且您担心操作数量,您可以在if语句中重新排序条件,以便在检查其他两个条件之前它们在flag!= 0上短路。即:
if( !flag1 && P[mid1]>=x && P[mid1-1]<x ) {...}
技术上比
更快if( P[mid1]>=x && P[mid1-1]<x && !flag1 ) {...}
接下来,除法可能是一项昂贵的操作......你要除以2.使用位移代替:
jump_size = jump_size >> 2
现在完全抛弃了标志,我们可能会重写代码看起来更像这样:
// n is the size of array P
// start int the middle
int pos1=pos2=n>>2;
// jump size is how far we jump up or down looking for our index
int jump_size=pos1>>2;
while(jump_size)
{
if(P[pos1]>x) { pos1 -= jump_size; }
else if(P[pos1]<x) { pos1+=jump_size; }
// similar for y and pos2
jump_size=jump_size>>2;
}
答案 2 :(得分:0)
您可以使用floor(x)
- ceil(y)
在O(日志N)时间内找到它
以下是查找ceil()
..
int ceilSearch(int arr[], int low, int high, int x)
{
int i;
/* If x is smaller than or equal to first element,
then return the first element */
if(x <= arr[low])
return low;
/* Otherwise, linearly search for ceil value */
for(i = low; i < high; i++)
{
if(arr[i] == x)
return i;
/* if x lies between arr[i] and arr[i+1] including
arr[i+1], then return arr[i+1] */
if(arr[i] < x && arr[i+1] >= x)
return i+1;
}
/* If we reach here then x is greater than the last element
of the array, return -1 in this case */
return -1;
}
您可以轻松修改它以使floor()
功能。
另一种方法是在使用lower_bound()
时使用upper_bound()
和c++
。