【问题标题】:Efficiently, get the count of numbers in a sorted array that is less than a given number using binary search有效地,使用二进制搜索获取排序数组中小于给定数字的数字计数
【发布时间】:2020-04-13 22:09:58
【问题描述】:

我的问题陈述是这样的—— 查找排序数组中小于给定数字的数字计数,这应该在时间上有效地完成。我使用二进制搜索编写了一个程序,该程序可以获取计数,但在时间复杂度方面它失败了。需要帮助来实现这一目标。

import java.util.Arrays;

public class SortedSearch {
    public static int countNumbers(int[] sortedArray, int lessThan) {
        if(sortedArray.length ==1 || sortedArray.length == 0) {
            return singleElement(sortedArray, lessThan);
        }
        else {
            return binarySearch(sortedArray, lessThan);
        }
    }

    public static int singleElement(int[] sortedArray, int searchVal) {
        if(sortedArray.length == 0) {
            return 0;
        }
        if(sortedArray[0] < searchVal) {
            return 1;
        }
        return 0;
    }

    private static int binarySearch(int[] sortedArray, int searchVal) {
        int low = 0;
        int high = (sortedArray.length)-1;
        int mid = (low + high)/2;
        if((sortedArray.length == 0) || (sortedArray[0] > searchVal)) {
            return 0;
        }
        if(sortedArray[high] < searchVal) {
            return sortedArray.length;
        }
        if(sortedArray[high] == searchVal) {
            return sortedArray.length-1;
        }
        if(sortedArray[mid] < searchVal) {
            int newLow = low;
            int newHigh = calculateNewHigh(sortedArray, newLow, 0, searchVal);
            int[] newArray = Arrays.copyOfRange(sortedArray, newLow, newHigh+1);
            return newArray.length;
        }
        else {
            int newLow = low;
            int newHigh = mid;
            int[] newArray = Arrays.copyOfRange(sortedArray, newLow, newHigh+1);
            return binarySearch(newArray, searchVal);
        }
    }

    private static int calculateNewHigh(int[] sortedArray, int low, int previousHigh, int searchVal) {
        int newHigh =  previousHigh + (sortedArray.length-low)/2;
        if(sortedArray[newHigh] < searchVal) {
            newHigh = calculateNewHigh(sortedArray, newHigh, newHigh, searchVal);
        }
        if(sortedArray[newHigh] == searchVal) {
            newHigh--;
        }
        if(sortedArray[newHigh] > searchVal) {
            newHigh--;
        }
        return newHigh;
    }

    public static void main(String[] args) {
        System.out.println(SortedSearch.countNumbers(new int[] { 1, 3, 5, 7 }, 4));
    }
}

【问题讨论】:

  • 不要使用copyOfRange。不需要复制数组的切片,或者根本不需要创建新数组,这会将性能降低到 O(n) 而不是 O(log n)。

标签: java sorting data-structures binary-search


【解决方案1】:

既然您无论如何都在使用Arrays,那么不要使用Arrays.binarySearch(int[] a, int key) 方法,而是尝试自己编写?

public static int countNumbers(int[] sortedArray, int lessThan) {
    int idx = Arrays.binarySearch(sortedArray, lessThan);
    if (idx < 0)
        return -idx - 1; // insertion point
    while (idx > 0 && sortedArray[idx - 1] == lessThan)
        idx--;
    return idx; // index of first element with given value
}

while 循环1 是必要的,因为 javadoc 说:

如果数组包含多个具有指定值的元素,则无法保证会找到哪一个。

1) 这个循环不是最优的,例如所有值都相同,请参见例如Finding multiple entries with binary search

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-08
    • 2016-02-11
    • 1970-01-01
    • 2019-07-15
    • 2017-11-20
    • 1970-01-01
    • 2013-05-22
    • 1970-01-01
    相关资源
    最近更新 更多