获取在log(n)时间内落在特定范围内的排序数组中的元素数

时间:2013-03-06 09:01:57

标签: java algorithm search big-o

假设我有一个以下类的数组,按y:

按升序排序
public class Obj {
    public int x;
    public int y;
}

如何在log(N)时间内找到y值在最小值和最大值范围内的数组中的Obj项数?

我已经考虑过使用二进制搜索来查找使用binarySearch和减去的min和max元素的位置,但是因为它搜索了两次,所以不会是2 log(n)吗?

public static int getNumberOfItems(Obj[] a, int min, int max) {

3 个答案:

答案 0 :(得分:4)

当您被要求在log(n)时间内执行某些操作时,这通常意味着O(log(n))

如果是这种情况,值得注意O(2 log(n)) == O(log(n)),即两者是相同的。

有关大写符号的更多背景信息,请参阅Wikipedia page

答案 1 :(得分:1)

bin搜索适用于该方法,O(log N)表示c * log N. 所以bin搜索没问题,但你可以通过搜索范围内的搜索范围(minFoundIndex,N)优化bin搜索调用maxIndex searchimg。

答案 2 :(得分:0)

这个问题与here相同,我提供了 O(logn)实现。

这个想法是通过范围二进制搜索下限和上限。对于您的示例,所有值都在讨论 y 值。


  1. 对于下限(左范围),您可以调用以下函数来获取值大于或等于它的有序数组中的索引,否则为-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. 对于上限(右侧范围),您可以调用以下函数来获取值小于或等于它的有序数组中的索引,否则为-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. 最后,如果您想获得此范围内的元素数量,可以根据上述两个函数的返回值轻松实现。

    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;
    

  4. 测试 :(带有重复项)

        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;