「二分」的本质是二段性,并非单调性。只要一段满足某个性质,另外一段不满足某个性质,就可以用「二分」。
# bisect.bisect_left
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = left + (right - left) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1package main
func BinarySearch(arr []int, target int) int {
left, right := 0, len(arr)-1
for left <= right {
mid := left + (right-left)/2
if arr[mid] == target {
return mid
} else if arr[mid] < target {
left = mid + 1
} else {
right = mid - 1
}
}
return -1
}package main
// 这里的二段性是一段满足<target,另一段不满足
func binarySearch(nums []int, left, right, target int) int {
l, r := left, right
for l < r {
mid := l + (r-l)/2
if nums[mid] < target {
l = mid + 1
} else {
r = mid
}
}
if nums[r] == target {
return r
}
return -1
}
func search(nums []int, target int) bool {
n := len(nums)
left, right := 0, n-1
// 恢复二段性
for left < right && nums[right] == nums[left] {
right--
}
// 这里的二段性是一段满足>=nums[0],另一段不满足
for left < right {
mid := left + (right-left+1)/2
if nums[mid] >= nums[0] {
left = mid
} else {
right = mid - 1
}
}
idx := n
if nums[right] >= nums[0] && right < n-1 {
idx = right + 1
}
if target >= nums[0] {
return binarySearch(nums, 0, idx-1, target) != -1
} else {
return binarySearch(nums, idx, n-1, target) != -1
}
}