为什么这个二分查找排序数组的场景还是会报错呢?
Why is there still an error case in this binary search of sorted array scenario?
郑重声明,我是在某个网络编码网站上遇到这个问题的,但我真正感兴趣的是我错过了什么,而不是分数。开始了:
实现函数 countNumbers,它接受经过排序的唯一整数数组,并计算小于参数 lessThan 的数组元素的数量。
例如SortedSearch.countNumbers(new int[] { 1, 3, 5, 7 }, 4)
应该return2
因为有两个数组元素小于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));
}
}
您的代码当前正在执行经典二分搜索。您需要 修改 以包含您的案例。
例如
使用以下测试用例尝试您的代码:
{ 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
更改。
while(left < right)
至
while(left <= right)
像您这样的二元搜索是我最讨厌的事情之一。我写了我认为通常在这里写一篇的最佳方式: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;
}
请注意,没有特殊情况需要处理,如果数组包含重复元素,这也适用。
郑重声明,我是在某个网络编码网站上遇到这个问题的,但我真正感兴趣的是我错过了什么,而不是分数。开始了:
实现函数 countNumbers,它接受经过排序的唯一整数数组,并计算小于参数 lessThan 的数组元素的数量。
例如SortedSearch.countNumbers(new int[] { 1, 3, 5, 7 }, 4)
应该return2
因为有两个数组元素小于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));
}
}
您的代码当前正在执行经典二分搜索。您需要 修改 以包含您的案例。
例如 使用以下测试用例尝试您的代码:
{ 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
更改。
while(left < right)
至
while(left <= right)
像您这样的二元搜索是我最讨厌的事情之一。我写了我认为通常在这里写一篇的最佳方式: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;
}
请注意,没有特殊情况需要处理,如果数组包含重复元素,这也适用。