[英]How to find number of integers in a sorted array that are within a certain range in O(log(N)) time?
I have a sorted array of integers: 我有一个排序的整数数组:
{1,2,4,4,5,8,12,15,15,23,54}
I want to find how many numbers in that array fall between a range, say 4 and 15. 我想知道该数组中有多少数字落在一个范围之间,例如4到15之间。
{4,4,5,6,12,15,15}
So, there are 7 items in the array that are within that range. 因此,阵列中有7个项目在该范围内。
I need to do this in O(log(N)) time, and I thought I could use a binary search, but that wouldn't find the lower and upper bounds because of the duplicates. 我需要在O(log(N))时间内执行此操作,并且我认为我可以使用二进制搜索,但由于重复,因此无法找到下限和上限。
How can this be done in O(log(N)) time? 如何在O(log(N))时间内完成?
I've thought of looping from the front, and then from the end, but that could be up to O(N) 我想过从前面循环,然后从最后循环,但这可能达到O(N)
It can be done in O(logN) time by range binary search for the lower bound and upper bound. 它可以在O(logN)时间内通过范围二进制搜索来完成下限和上限。 Range binary search for the lower bound and the upper bound are different .
下限和上限的范围二进制搜索是不同的 。 Here different means they have different stopping criteria and return step.
这里不同意味着它们具有不同的停止标准和返回步骤。
For the lower bound (left range) , you can call the following function to get the index in the sorted array where the value is larger or equal than it, -1 otherwise. 对于下限(左范围) ,您可以调用以下函数来获取值大于或等于它的排序数组中的索引,否则为-1。
int binarySearchForLeftRange(int a[], int length, int left_range) { if (a[length-1] < left_range) return -1; int low = 0; int high = length-1; while (low<=high) { int mid = low+((high-low)/2); if(a[mid] >= left_range) high = mid-1; else //if(a[mid]<i) low = mid+1; } return high+1; }
For the upper bound (right range) , you can call the following function to get the index in the sorted array where the value is smaller or equal than it, -1 otherwise. 对于上限(右侧范围) ,您可以调用以下函数来获取排序数组中的索引,其中值小于或等于它,否则为-1。
int binarySearchForRightRange(int a[], int length, int right_range) { if (a[0] > right_range) return -1; int low = 0; int high = length-1; while (low<=high) { int mid = low+((high-low)/2); if(a[mid] > right_range) high = mid-1; else //if(a[mid]<i) low = mid+1; } return low-1; }
Finally , if you want to get the number of how many elements within this range, it's easy based on return values of these two above functions. 最后 ,如果您想获得此范围内的元素数量,则可以根据上述两个函数的返回值轻松实现。
int index_left = binarySearchForLeftRange(a, length, left_range); int index_right = binarySearchForRightRange(a, length, right_range); if (index_left==-1 || index_right==-1 || index_left>index_right) count = 0; else count = index_right-index_left+1;
Test : (with duplicates) 测试 :(有重复)
int a[] = {1,2,4,4,5,8,12,15,15,23,54};
int length = sizeof(arr)/sizeof(arr[0]);
int left_range = 4;
int right_range = 15;
int index_left = binarySearchForLeftRange(a, length, left_range); // will be 2
int index_right = binarySearchForRightRange(a, length, right_range); // will be 8
int count; // will be 7
if (index_left==-1 || index_right==-1 || index_left>index_right)
count = 0;
else
count = index_right-index_left+1;
EDIT : Of course, you can merge the first two functions into one by passing one extra flag to indicate it as lower bound or upper bound, though it will be much more clear if not. 编辑 :当然,您可以通过传递一个额外的标志来将前两个函数合并为一个,以指示它是下限或上限,但如果不是,则会更清楚。 Your choice!
你的选择!
In Binary Search, you stop the recursive procedure when you find the required number or when the number is not in the list. 在二进制搜索中,当您找到所需的数字或数字不在列表中时,您将停止递归过程。
Here, you have to modify the Binary Search algorithm. 在这里,您必须修改二进制搜索算法。 Start with lower range, say a , keep repeating until you find a number less than a .
与较低的范围开始, 说 ,不断重复,直到你找到了一些不足 。 While doing this maintain two indices say low and high .
在这样做的同时保持两个指数,即低点和高点 。 If the number you are comparing is less than a , update low else update high.
如果您要比较的数字小于a ,则更新低其他更新高。 Now you have the lower index, now recursively apply this procedure to find the number greater than this a .
现在你有较低的指数,现在应用这个递归过程来找到一个比这更大的数量。 This index will give the starting index.
该索引将给出起始索引。
Now, do the complimentary for upper range, you'll get the ending index. 现在,做上限范围的免费赠送,您将获得结束指数。
The answer is ending index - starting index + 1
答案是
ending index - starting index + 1
imin = 0, imax = A.size()-1
low = 0, high = A.size()-1
while(imax >= imin)
{
imid = mid(imin,imax)
if(key < A[imid])
{
imax = imid -1
high = imid
}
else if(key > A[imid])
{
imin = imid + 1
low = imid
}
else
{
high = imid
break;
}
}
Now, once it comes out of the loop check if imin > imax
, if yes then lower range index would be imax. 现在,一旦它从循环中检出
imin > imax
,如果是,则较低范围索引将是imax。 Else, repeat the search again with imin = low
and imax = high
with the same key, till you reach the condition imin > imax
. 否则,使用相同的键再次使用
imin = low
和imax = high
重复搜索,直到达到imin > imax
的条件。 Repeat the same for the upper range. 对上限范围重复相同的操作。
The time complexity falls between O(log(n))
and O(n)
时间复杂度介于
O(log(n))
和O(n)
You need a modified binary search, one that has a parameter whether to find the first or last occurence of element. 您需要一个修改过的二进制搜索,它具有一个参数,无论是查找元素的第一个还是最后一个。
You have to write yourself that modified binsearch. 您必须自己编写修改后的binsearch。
I am not explaining I have given the code in java if you want you can improve it. 我没有解释我已经在java中给出了代码,如果你想要你可以改进它。
public class Test {
public static int binSearch(int array[], int key, int left, int right,boolean lb)
{
int mid = left + (right-left)/2;
if (key < array[mid])
return binSearch(array, key, left, mid-1,lb);
else if (key > array[mid])
return binSearch(array, key, mid+1, right,lb);
else if (key == array[mid]){
if(!lb){
if(key==array[mid+1]){
int ctr=mid+1;
while(key==array[++ctr]);
return ctr--;
}
else
return mid;
}
else{
if(key==array[mid-1]){
int ctr=mid-1;
while(key==array[--ctr]);
return ctr++;
}
else
return mid;
}
}
return -0; // Not Found
} }
public static void main(String[] args) {
int a[]={1,2,4,4,5,8,12,15,15,23,54};
int start=binSearch(a, 4, 0, a.length,true);
int end=binSearch(a, 15, 0, a.length,false);
System.out.println(end-start+1);// number are include
}
} }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.