给定排序整数数组,搜索关键字和搜索首选项查找数组位置。搜索首选项可以是:
1) EQUAL – 仅搜索等号,如果未找到则为 -1。这是一个常规的二分查找。
2) EQUAL_OR_SMALLER – 仅搜索相等的键或最接近的较小的键。 -1 如果没有找到。
3) EQUAL_OR_BIGGER – 只搜索相等的键或最接近的更大的键。 -1 如果没有找到。
例子:
Input : { 0, 2, 4, 6 }, key -1, EQUAL
Output : -1
Input : { 0, 2, 4, 6 }, key -1, EQUAL_OR_BIGGER
Output : 0
Input : { 0, 2, 4, 6 }, key 7, EQUAL_OR_BIGGER
Output : -1
Input : { 0, 2, 4, 6 }, key 7, EQUAL_OR_SMALLER
Output : 3
在常规二分搜索算法中,只要子数组大小大于 0,就会执行评估和除法。
在我们的例子中,如果我们想保留单个函数,我们需要在 size=2 的子数组中执行最终评估。只有在 subarray size==2 中才能同时检查 EQUAL_OR_SMALLER 和 EQUAL_OR_BIGGER 条件。
在下面的代码中, SC 代表 Search Criteria 。
public class BinarySearchEqualOrClose {
private static void printResult(int key, int pos,
SC sC)
{
System.out.println("" + key + ", " + sC + ":" + pos);
}
enum SC {
EQUAL,
EQUAL_OR_BIGGER,
EQUAL_OR_SMALLER
};
public static int searchEqualOrClose(int key, int[] arr, SC sC)
{
if (arr == null || arr.length == 0) {
return -1;
}
if (arr.length == 1) { // just eliminate case of length==1
// since algorithm needs min array size==2
// to start final evaluations
if (arr[0] == key) {
return 0;
}
if (arr[0] < key && sC == SC.EQUAL_OR_SMALLER) {
return 0;
}
if (arr[0] > key && sC == SC.EQUAL_OR_BIGGER) {
return 0;
}
return -1;
}
return searchEqualOrClose(arr, key, 0, arr.length - 1, sC);
}
private static int searchEqualOrClose(int[] arr, int key,
int start, int end, SC sC)
{
int midPos = (start + end) / 2;
int midVal = arr[midPos];
if (midVal == key) {
return midPos; // equal is top priority
}
if (start >= end - 1) {
if (arr[end] == key) {
return end;
}
if (sC == SC.EQUAL_OR_SMALLER) {
// find biggest of smaller element
if (arr[start] > key && start != 0) {
// even before if "start" is not a first
return start - 1;
}
if (arr[end] < key) {
return end;
}
if (arr[start] < key) {
return start;
}
return -1;
}
if (sC == SC.EQUAL_OR_BIGGER) {
// find smallest of bigger element
if (arr[end] < key && end != arr.length - 1) {
// even after if "end" is not a last
return end + 1;
}
if (arr[start] > key) {
return start;
}
if (arr[end] > key) {
return end;
}
return -1;
}
return -1;
}
if (midVal > key) {
return searchEqualOrClose(arr, key, start, midPos - 1, sC);
}
return searchEqualOrClose(arr, key, midPos + 1, end, sC);
}
public static void main(String[] args)
{
int[] arr = new int[] { 0, 2, 4, 6 };
// test full range of xs and SearchCriteria
for (int x = -1; x <= 7; x++) {
int pos = searchEqualOrClose(x, arr, SC.EQUAL);
printResult(x, pos, SC.EQUAL);
pos = searchEqualOrClose(x, arr, SC.EQUAL_OR_SMALLER);
printResult(x, pos, SC.EQUAL_OR_SMALLER);
pos = searchEqualOrClose(x, arr, SC.EQUAL_OR_BIGGER);
printResult(x, pos, SC.EQUAL_OR_BIGGER);
}
}
}
输出:
-1, EQUAL:-1
-1, EQUAL_OR_SMALLER:-1
-1, EQUAL_OR_BIGGER:0
0, EQUAL:0
0, EQUAL_OR_SMALLER:0
0, EQUAL_OR_BIGGER:0
1, EQUAL:-1
1, EQUAL_OR_SMALLER:0
1, EQUAL_OR_BIGGER:1
2, EQUAL:1
2, EQUAL_OR_SMALLER:1
2, EQUAL_OR_BIGGER:1
3, EQUAL:-1
3, EQUAL_OR_SMALLER:1
3, EQUAL_OR_BIGGER:2
4, EQUAL:2
4, EQUAL_OR_SMALLER:2
4, EQUAL_OR_BIGGER:2
5, EQUAL:-1
5, EQUAL_OR_SMALLER:2
5, EQUAL_OR_BIGGER:3
6, EQUAL:3
6, EQUAL_OR_SMALLER:3
6, EQUAL_OR_BIGGER:3
7, EQUAL:-1
7, EQUAL_OR_SMALLER:3
7, EQUAL_OR_BIGGER:-1
时间复杂度:O(log n)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。