为什么在这种排序数组情况的二进制搜索中仍然存在错误情况?

时间:2018-08-18 10:43:00

标签: java algorithm sorting data-structures binary-search

为了记录,我在某个Web编码站点上遇到了这个问题,但是我对我错过的内容而不是分数很感兴趣。在这里:

实现函数countNumbers,该函数接受排序的唯一整数数组,并计算小于参数lessThan的数组元素的数量。

例如,SortedSearch.countNumbers(new int[] { 1, 3, 5, 7 }, 4)应该返回2,因为有两个数组元素少于4

我提供以下解决方案,但是,我无法确定在哪种情况下它将失败? (该网站表示未通过4个测试中的1个)。而且我也不确定我可以对值lessThan做出什么样的假设。

public class SortedSearch {
    public static int countNumbers(int[] sortedArray, int lessThan) {

        if (sortedArray == null || sortedArray.length == 0)
            return 0;

        if (sortedArray.length == 1) {
            return sortedArray[0] < lessThan? 1:0;
        }

        int left = 0;
        int right = sortedArray.length-1;
        int middle = 0;

        while(left<right) {
            middle = left + (right-left)/2;
            if (sortedArray[middle]<lessThan) {
                left = middle+1;
            } else if (sortedArray[middle]>lessThan) {
                right = middle-1;
            } else {
                return middle;
            }        
        }
        return left;

    }

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

3 个答案:

答案 0 :(得分:2)

您的代码当前正在执行经典二进制搜索。您需要修改以包括您的案件。

例如。 尝试使用以下测试用例编写代码:

{ 1, 3, 5 }, 4) -> should output 2
{ 1, 3, 5 }, 2) -> should output 1
{ 1, 3, 5 }, 3) -> should output 1
{ 1, 3, 5 }, 6) -> should output 3
{ 1, 3, 5 }, 0) -> should output 0

其中大多数都无法使用现有代码。

我们的目标是找出给定数字middle 小于middle + 1 大于的点。当然,我们可以使用二进制搜索(已修改)来做到这一点。

我修改了您的经典二进制搜索代码,以包括以下情况(以及代码中添加的注释):

while (left <= right) {
    middle = left + (right - left) / 2;
    if (sortedArray[middle] < lessThan && (middle + 1) < sortedArray.length
            && sortedArray[middle + 1] > lessThan) {
        // we have the point where middle is less and middle+1 is greater than given num
        return middle + 1;
    } else if (sortedArray[middle] == lessThan) {
        // we have found the number itself
        return middle;
    } else if (sortedArray[middle] < lessThan) {
        // recur in right part
        left = middle + 1;
    } else if (sortedArray[middle] > lessThan) {
        // recur in left part
        right = middle - 1;
    }
}

// given number is either lesser/bigger than all elements in the array
return lessThan < sortedArray[0] ? 0 : sortedArray.length;

答案 1 :(得分:1)

仅更改1

  

while(左<右)

  

while(左<=右)

答案 2 :(得分:1)

像您一样的二进制搜索功能是我的宠儿之一。我写了一些我认为通常是在此处写的最好方法:How can I simplify this working Binary Search code in C?

这特别适合您的情况。由于您尝试查找位置而不是元素,因此可以通过每次迭代仅进行一次比较来简化代码并使之更快:

public static int countNumbers(int[] sortedArray, int lessThan) {
    int start = 0, limit = sortedArray.length;
    while(start < limit) {
        int test = start + ((limit-start)>>1);
        if (sortedArray[test] < lessThan) {
            start = test+1;
        } else {
            limit = test;
        }
    }
    return start;
}

请注意,没有特殊情况需要处理,如果数组包含重复的元素,这也将起作用。