一、上下界
上边界 upper:表示 >= target 的位置
下边界 lower:表示 <= target 的位置
绝对上边界 abs_upper:表示 > target 的位置,与上边界的关系:lower = abs_upper - 1
绝对下边界 abs_lower:表示 < target 的位置,与下边界的关系:upper = abs_lower + 1
二、二分查找
1、标准库的二分查找
// len(nums) 表示未找到
func upperBound0(nums []int, target int) int {
//upper := sort.SearchInts(nums, target)
upper := sort.Search(len(nums), func(i int) bool {
return nums[i] >= target
})
return upper
}
// -1表示未找到
func lowerBound0(nums []int, target int) int {
lower := sort.Search(len(nums), func(i int) bool {
return nums[i] > target // 绝对上界限
}) - 1
return lower
}
2、二分查找
<= 结果是可能是:i=j (同时位于相等位置)、i!=j (j位于下边界,i位于上边界)
< 结果是可能是:i=j (同时位于相等位置)、i=j (同时位于下边界)、i=j (同时位于上边界)
mid = (l + r) / 2 存在越界问题
mid = int(uint(l + r) >> 1) 标准库的高效写法
方式一:<=
func upperBound1(nums []int, target int) int {
l, r := 0, len(nums)-1
// <= 结果是可能是:i=j (同时位于相等位置)、i!=j (j位于下边界,i位于上边界)
// < 结果是可能是:i=j (同时位于相等位置)、i=j (同时位于下边界)、i=j (同时位于上边界)
for l <= r {
mid := (l + r) / 2
if nums[mid] == target {
return mid
}
if nums[mid] > target {
r = mid - 1
} else {
l = mid + 1
}
}
return l
}
func lowerBound1(nums []int, target int) int {
l, r := 0, len(nums)-1
// <= 结果是可能是:i=j (同时位于相等位置)、i!=j (j位于下边界,i位于上边界)
// < 结果是可能是:i=j (同时位于相等位置)、i=j (同时位于下边界)、i=j (同时位于上边界)
for l <= r {
mid := (l + r) / 2
if nums[mid] == target {
return mid
}
if nums[mid] > target {
r = mid - 1
} else {
l = mid + 1
}
}
return r
}
方式二:<
func upperBound2(nums []int, target int) int {
l, r := 0, len(nums)-1
// <= 结果是可能是:i=j (同时位于相等位置)、i!=j (j位于下边界,i位于上边界)
// < 结果是可能是:i=j (同时位于相等位置)、i=j (同时位于下边界)、i=j (同时位于上边界)
for l < r {
mid := (l + r) / 2
if nums[mid] == target {
return mid
}
if nums[mid] > target {
r = mid - 1
} else {
l = mid + 1
}
}
//l是上边界
if nums[l] >= target {
return l
}
//l+1是上边界
return l + 1
}
func lowerBound2(nums []int, target int) int {
l, r := 0, len(nums)-1
// <= 结果是可能是:i=j (同时位于相等位置)、i!=j (j位于下边界,i位于上边界)
// < 结果是可能是:i=j (同时位于相等位置)、i=j (同时位于下边界)、i=j (同时位于上边界)
for l < r {
mid := (l + r) / 2
if nums[mid] == target {
return mid
}
if nums[mid] > target {
r = mid - 1
} else {
l = mid + 1
}
}
//l是下边界
if nums[l] <= target {
return l
}
//l-1是下边界
return l - 1
}