参考C++库函数来划分二分查找元素的四个边界
704. 二分查找
# 求非降序范围[first, last)内第一个不小于value的值的位置
def lower_bound(array, first, last, value):
while first < last: # 搜索区间[first, last)不为空
mid = first + (last - first) // 2 # 防溢出
if array[mid] < value: first = mid + 1
else: last = mid
return first # last也行,因为[first, last)为空的时候它们重合
def upper_bound(array, first, last, value):
while first < last:
mid = first + (last - first) // 2
if array[mid] <= value: first = mid + 1
else: last = mid
return first
-
lower_bound(value)本身找的是x>=value的下界,若为last则不存在(第二个箭头)
-
upper_bound(value)本身找的是x>value的下界,若为last则不存在(第四个箭头)
-
lower_bound(value)-1即为x< value的上界,若为first-1则不存在(第一个箭头)
-
upper_bound(value)-1即为x<= value的上界,若为first-1则不存在(第三个箭头)
class Solution {
public int search(int[] nums, int target) {
int first = 0, last = nums.length;
while (first < last) {
int mid = first + ((last - first) >> 1);
if (nums[mid] < target) first = mid + 1;
else last = mid;
}
if (first == nums.length || nums[first] != target) return -1;
return first;
}
}
34. 在排序数组中查找元素的第一个和最后一个位置
这题对应上文图片中第二个箭头和第三个箭头。
class Solution {
int target;
public int[] searchRange(int[] nums, int target) {
this.target = target;
int lower = lower_bound(nums, 0, nums.length);
int upper = upper_bound(nums, 0, nums.length);
return new int[]{lower, upper};
}
public int lower_bound(int[] nums, int first, int last) {
while (first < last) {
int mid = first + ((last - first) >> 1);
if (nums[mid] < target) first = mid + 1;
else last = mid;
}
if (first == nums.length || nums[first] != target) return -1;
return first;
}
public int upper_bound(int[] nums, int first, int last) {
while (first < last) {
int mid = first + ((last - first) >> 1);
if (nums[mid] <= target) first = mid + 1;
else last = mid;
}
if (!(first - 1 >= 0 && nums[first - 1] == target)) return -1;
return first - 1;
}
}