二分查找算法
闭区间写法
对于闭区间写法来说,返回的left是第一个找到的target对应的下标,返回的right是left-1,因此一般返回left,如果target > max(nums)
,则会返回len(nums)
,若target < min(nums)
,则会返回0
,若min(nums) < target< max(nums)
,但是不存在数组中,则会返回第一个大于此数的下标
// 闭区间写法
func lowerBoundBothClosedInterval(nums []int, target int) int {
left, right := 0, len(nums)-1
for left <= right {
mid := left + (right-left)/2
if nums[mid] < target {
left = mid + 1
} else {
right = mid - 1
}
}
return left
}
左闭右开区间
对于左闭右开区间写法来说,返回的left是第一个找到的target对应的下标,返回的right等于left,因此随便返回哪个,如果target > max(nums)
,则会返回len(nums)
,若target < min(nums)
,则会返回0
,若min(nums) < target< max(nums)
,但是不存在数组中,则会返回第一个大于此数的下标
// 左闭右开区间
func lowerBoundLeftClosedRightOpen(nums []int, target int) int {
left, right := 0, len(nums)
for left < right {
mid := left + (right-left)/2
if nums[mid] < target {
left = mid + 1
} else {
right = mid
}
}
return left
}
开区间写法
对于开区间写法来说,返回的right是第一个找到的target对应的下标,返回的left==left-1,因此返回right,如果target > max(nums)
,则会返回len(nums)
,若target < min(nums)
,则会返回0
,若min(nums) < target< max(nums)
,但是不存在数组中,则会返回第一个大于此数的下标
func lowerBoundBothOpenInterval(nums []int, target int) int {
left, right := -1, len(nums)
for left+1 < right {
mid := left + (right-left)/2
if nums[mid] < target {
left = mid
} else {
right = mid
}
}
return right
}
tip
如果想要在例如{1,2,3,3,3,3,4}的数组中找到最右边的3怎么办?
我们只需要将target改为3 + 1,然后将答案-1即可
便于记忆方法
闭区间对应更加合理的left和right范围,因此所有闭区间的地方都会在合理的下标中,如left=0,right=len(nums)-1
,但是变成开区间后,左会更左,右会更右。在循环中,凡是闭区间left = mid + 1 , right = mid - 1
,否则left = mid , right = mid