前言
虽然二分搜索很简单(在无重复的有序数组上),但是也有很多值得注意的地方,而且有两种完全不同的写法(两种完全不同的功能)
lower bound
找出大于等于target的最小数组下标, 不存在的情况下返回-1
func lower_bound(a []int, target int) int {
l := 0
h := len(a) - 1
for l < h {
m := l + (h - l) / 2
if a[m] < target {
// l肯定可以取到h值,所以不需要使用向上取整计算m值
l = m + 1
} else {
h = m
}
}
if a[l] >= target {
return l
}
return -1
}
upper bound
找出小于等于target的最大数组下标
func upper_bound(a []int, target int) int {
l := 0
h := len(a) - 1
for l < h {
m := l + (h - l + 1) / 2
if a[m] <= target {
// l 要能够取到h值,就必须保证m使用向上取整计算, (h - l + 1) / 2 就是这么来的
l = m
} else {
h = m - 1
}
}
if a[l] <= target {
return l
}
return -1
}
注意点
- 计算mid的时候不能发生溢出
- 数组下标不能越界