根据灵神教学中的二分查找开区间写法进行如下总结:
我们需要注意的是,lowerBound 模板求解的是 >= target 的最小下标
private int lowerBound(int[] nums, int target) {
int left = -1;
int right = nums.length; // 开区间 (left, right)
while (left + 1 < right) { // 区间不为空
// 循环不变量:
// nums[left] < target
// nums[right] >= target
int mid = left + ((right - left) > 1);// 避免溢出的同时位运算加快运算速度
if (nums[mid] < target) {
left = mid; // 范围缩小到 (left, mid)
} else {
right = mid; // 范围缩小到 (mid, right)
}
}
// 循环结束后 left+1 = right
// 此时 nums[left] < target 而 nums[right] >= target
// 所以 right 就是第一个 >= target 的元素下标
return right;
}
那么如果我们要求的是 > / < / <= 这三类的该怎么处理呢?
在整型的条件下,其实是同一类问题,都转化成 >= 模板就可以了,
- > x 等价于 >= x+1
- < x 等价于 >= x 的左边一个
- <= x 等价于 > x 或 >= x + 1的左边一个
// > 情况
// nums[right] >= target + 1
if (nums[mid] < target + 1)
// < 情况
// nums[right] >= target
if (nums[mid] < target)
...
return right - 1
// <= 情况
// nums[right] >= target + 1
if (nums[mid] < target + 1)
...
return rigth - 1
如果没有找到会有哪些情况?
- right == nums.length ,target > 数组中的所有元素
- nums[right] != target , 数组中不存在target