问题
有这样的问题:如果递增序列 A 中的元素可能重复,那么如何对给定的欲查询元素x,求出序列中第一个大于等于x的元素的位置L以及第一个大于x 的元素的位置R。
序列中第一个大于等于x的元素的位置
先看第一问
例如对下标从0开始、有5个元素的序列 {1,3,3,3,6}
来说,如果要查询 3,则应当得到 L=1、R=4;如果查询 5,则应当得到L=R=4;如果查询 6,则应当得到 L=4、R=5;而如果查询8,则应当得到L=R=5。
显然,如果序列中没有x,那么L和R也可以理解为假设序列中存在x,则x应当在的位置。
那么既然 L和R 可能会等于 5,那也就是说 R 的起始值不是 4,而是 5,这是因为二分法返回的范围只能是 L到R 的区间,如果初始 R 为 4,那如果没有查询到的话,只能返回 4,就不会出现查询 8 返回 L=R=5 的情况了
查询情况
假设存在序列 A,当前二分区间为 [left,right](left为0, right为数组长度)
-
如果 A[mid] >= x,说明第一个大于等于 x 的元素的位置一定在 mid 处或者 mid 的左侧,应该往左子区间[left,mid]继续查询,即令 right = mid
-
如果 A[mid] < x,说明第一个大于等于 x 的元素的位置一定在 mid 的右侧,应该往右子区间 [mid + 1,right] 继续查询,即令 left= mid + 1
如图很容易写出代码
代码
// A[] 为递增序列,x 为欲查询的数,函数返回第一个大于等于 x 的元素的位置
// 二分上下界为左闭右闭[left, right],传入的初始值为 [0, n]
public static int lower_bound(int[] A, int left, int right, int x) {
int mid; // mid 为 left 和 right 的中点
whi