大多数情况 Binary Search 是以 index 为搜索范围,但是也可以来搜索 value。例如,LC287。
经典题目
First, we use k/2 as our step length to pick two numbers from arrayA and arrayB starting from index 0. Then we keep the larger number, and move the left boundary of the array which has the smaller number. In this case, we could remove k/2 numbers, and we just need to find (k - k / 2)th smallest in the remaining numbers. Then, we use k/4 as our step, and do the same step as above, and then k/8, k/16... Until k == 1, then just return the smaller of the current two numbers.
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int aLength = nums1.length;
int bLength = nums2.length;
int length = aLength + bLength;
if (length % 2 == 0) {
int a = findKthSmallest(nums1, 0, nums2, 0, length / 2);
int b = findKthSmallest(nums1, 0, nums2, 0, length / 2 + 1);
return (a + b) / 2.0;
} else {
return 1.0 * findKthSmallest(nums1, 0, nums2, 0, length / 2 + 1);
}
}
private int findKthSmallest(int[] a, int aLeft, int[] b, int bLeft, int k) {
if (aLeft >= a.length) {
return b[bLeft + k - 1];
} else if (bLeft >= b.length) {
return a[aLeft + k - 1];
} else if (k == 1) {
return Math.min(a[aLeft], b[bLeft]);
}
int aKthLeft = aLeft + k / 2 - 1 < a.length ? a[aLeft + k / 2 - 1] : Integer.MAX_VALUE;
int bKthLeft = bLeft + k / 2 - 1 < b.length ? b[bLeft + k / 2 - 1] : Integer.MAX_VALUE;
if (aKthLeft < bKthLeft) {
return findKthSmallest(a, aLeft + k / 2, b, bLeft, k - k / 2);
} else {
return findKthSmallest(a, aLeft, b, bLeft + k / 2, k - k / 2);
}
}
public int kthSmallest(int[][] matrix, int k) {
int n = matrix.length, m = matrix[0].length;
int lo = matrix[0][0], hi = matrix[n - 1][m - 1];
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
int j = m - 1;
int count = 0;
for (int i = 0; i < n; i++) {
while (j >= 0 && matrix[i][j] > mid) {
j -= 1;
}
count += (j + 1);
}
if (count < k) {
lo = mid + 1;
} else {
hi = mid;
}
}
return hi;
}
class Solution {
/*
Method 1: Random & Binary Search.
Time Complexity: O(log n)
Get the total number, get a random number from [1, sum], find where it's located
*/
int[] array;
Random rd = new Random();
public Solution(int[] w) {
array = new int[w.length];
for (int i = 0; i < w.length; i++) {
array[i] = (i == 0 ? w[i] : w[i] + array[i - 1]);
}
}
public int pickIndex() {
int num = rd.nextInt(array[array.length - 1]) + 1;
int left = 0, right = array.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (array[mid] < num) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
}