給定已排序數組 a[0:n-1],實現二分搜索:若目標值 x 存在,返回其位置作為 i 和 j;若不存在,返回 i 為小於 x 的最大元素位置,j 為大於 x 的最小元素位置。
遞歸二分搜索,維護區間 [i, j]:
i > j:未找到,answer[0]=j(最後一個 < x),answer[1]=i(第一個 > x)x == arr[mid]:找到,i=j=midx < arr[mid]:遞歸左半部 [i, mid-1]x > arr[mid]:遞歸右半部 [mid+1, j]import java.util.Arrays;
import java.util.Scanner;
public class BinarySearchBounds {
static int target;
// 遞歸查找,answer[0]=i, answer[1]=j
static void search(int left, int right, int[] arr, int[] answer) {
if (left > right) { // 未找到
answer[0] = right; // 最大的 < x
answer[1] = left; // 最小的 > x
return;
}
int mid = left + (right - left) / 2;
if (target == arr[mid]) {
Arrays.fill(answer, mid);
} else if (target < arr[mid]) {
search(left, mid - 1, arr, answer);
} else {
search(mid + 1, right, arr, answer);
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int n = scanner.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; ++i) arr[i] = scanner.nextInt();
target = scanner.nextInt();
int[] answer = new int[2];
search(0, n - 1, arr, answer);
System.out.println(answer[0] + " " + answer[1]);
}
scanner.close();
}
}
left + (right-left)/2 避免溢出left > right 時 right 指向最後一個 < x,left 指向第一個 > x,符合插入位置語義static void searchIterative(int[] arr, int[] ans) {
int l = 0, r = arr.length - 1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (target == arr[mid]) { ans[0] = ans[1] = mid; return; }
else if (target < arr[mid]) r = mid - 1;
else l = mid + 1;
}
ans[0] = r; ans[1] = l; // 退出時 l = r+1,r 為最後 < x,l 為第一 > x
}
此變體常用於:區間查詢前驅/後繼、離散化坐標壓縮、動態維護有序集合的 lower_bound/upper_bound 邏輯。