所谓二分查找,针对的是一个有序的数据集合(这点很重要),查找思想有点类似分治思想 —— 每次都通过跟区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为 0。
package main
import (
"fmt"
"sort"
)
// 二分查找实现代码
func binarySearch(nums []int, num int, low int, high int) int {
// 递归终止条件
if low > high {
return -1
}
// 通过中间元素进行二分查找
mid := (low + high) / 2
// 递归查找
if num > nums[mid] {
// 如果待查找数据大于中间元素,则在右区间查找
return binarySearch(nums, num, mid + 1, high)
} else if num < nums[mid] {
// 如果待查找数据小于中间元素,则在左区间查找
return binarySearch(nums, num, low, mid - 1)
} else {
// 找到了,返回索引值
return mid
}
}
func main() {
nums := []int{4, 6, 5, 3, 1, 8, 2, 7}
sort.Ints(nums) // 先对待排序数据序列进行排序
fmt.Printf("Sorted nums: %v\n", nums)
num := 5
index := binarySearch(nums, num, 0, len(nums)-1)
if index != -1 {
fmt.Printf("Find num %d at index %d\n", num, index)
} else {
fmt.Printf("Num %d not exists in nums\n", num)
}
}
性能分析
O(logn)
。这是一个非常恐怖的数量级,有时候甚至比 O(1)
还要高效,比如我们要在开头提到的 40 亿个数字中查找某一个元素,也只需要32次(2 的 32 次方是 40 亿数量级),这真的是非常高效了,正因如此,二分查找在线性表结构中的应用非常广泛。
About the author