二分查找(binary search),也称折半搜索(half-interval search)、对数搜索(logarithmic search),是一种在有序数组中查找某一特定元素的搜索算法。
搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。
场景1:返回第一次匹配中的目标值,GO代码实现如下:
//nums是有序数组
func binarySearch(nums []int, target int) int {
left, right := 0, len(nums)-1
for left <= right {
mid := (left + right) / 2
if nums[mid] == target {
return mid
} else if nums[mid] > target {
right = mid - 1
} else {
left = mid + 1
}
}
return -1
}
时间复杂度:O(\log n)O(logn),其中 nn 是数组的长度。
场景2:数组有重复元素的情况下,返回目标值在数组中最小索引位置,GO代码实现如下:
func binarySearchLeftBound(nums []int, target int) int {
left, right := 0, len(nums)-1
for left <= right {
mid := (left + right) / 2
if nums[mid] > target {
right = mid - 1
} else if nums[mid] < target {
left = mid + 1
} else {
right = mid - 1
}
}
//没有匹配值
if left == len(nums) || nums[left] != target {
return -1
}
return left
}
场景3:数组有重复元素的情况下,返回目标值在数组中最大索引位置,GO代码实现如下:
func binarySearchRightBound(nums []int, target int) int {
left, right := 0, len(nums)-1
for left <= right {
mid := (left + right) / 2
if nums[mid] > target {
right = mid - 1
} else if nums[mid] < target {
left = mid + 1
} else {
left = mid + 1
}
}
if right<0 || nums[right] != target {
return -1
}
return right
}