简体   繁体   English

如何在O(log(N))时间内找到排序数组中在一定范围内的整数数?

[英]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. 这里不同意味着它们具有不同的停止标准和返回步骤。

  1. 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; } 
  2. 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; } 
  3. 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 = lowimax = 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.

相关问题 高效算法在O(log(N))时间内找到排序数组中在一定范围内的整数数量? - Efficient algo to find number of integers in a sorted array that are within a certain range in O(log(N)) time? 给定排序列表如何创建在 O(log(N)) 时间内不会落在某个范围内的整数列表? - Given sorted list how to create list of integers that wont fall in certain range in O(log(N)) time? 获取排序数组中属于log(n)时间的特定范围内的元素数 - Get number of elements in a sorted array that fall within a certain range in log(n) time 如何在排序数组上使用二进制搜索来查找特定范围内的整数数。 (有重复) - How to use a binarysearch on a sorted array to find the number of integers within a certain range. (with duplicates) 以O(log n)复杂度计算排序数组中值的出现次数 - Count the number of appearances of a value in a sorted array in O(log n) complexity 在 O(1) 时间内获取排序数组中给定范围内的元素总数 - Obtain the Total number of element in the Sorted Array that are within the given Range in O(1) time 如何在O(n)中的排序数组中找到两个总和为给定数字的数字? - How to find two number whose sum is given number in sorted array in O(n)? 在 O(n * log n) 时间内找到 Array 中加起来等于目标数的两个元素 - Find Two elements in the Array that add up to the Target number in O(n * log n) Time 给定一个+ ve整数数组,找到在O(n)时间和常数空间中出现奇数次的数字。 - Given an array of +ve integers, Find the number which occurs odd number of times in O(n) time & constant space. 在 O(n) 时间内在已排序的链表中查找重复项 - find duplicates in a sorted linkedlist in O(n) time
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM