leetcode 704 二分查找(一)—— 在排序数组中查找

223 阅读1分钟

二分查找(Binary Search)也叫折半查找。二分查找将顺序遍历搜索的时间复杂度O(n)O(n)优化到了O(logn)O(logn)。二分查找有两个要求,一个是数列有序,另一个是数列使用顺序存储结构(比如数组)。

听说“二分查找算法发明多年之后才第一次被写对”。让我们一起把它写正确吧。

力扣题目链接

本题关键点:

  • 有序的(升序) 数组
  • 你可以假设数组中的所有元素是不重复

今天结合代码讲一讲二分查找。重点都在注释里。对于本题来说元素是否重复无所谓,找到任意一个返回其索引就是了。

// 在nums中找target。
// 如果存在返回下标。
// 如果不存在就返回-1。
func search(nums []int, target int) int {
    l := len(nums)
    if l == 0 {
        return -1
    }
    var (
        // 初始两端索引,限定一个左闭右闭区间
        low int
        high = l-1
    )
    for low <= high { // 这里要包含“等于”。具体原因在下面。
        // 找中间位置。
        // 当 low == high 时,算出来的mid和它们相等。
        // target也要和这个位置的值比较的。
        // 所以for循环的判断条件中要包含“等于”。
        // 计算mid可以用(low+high)/2,但加法计算结果可能溢出(不是针对本题)。所以换一种写法。
        // >>1 就是除以2。
        mid := low + (high-low)>>1
        v := nums[mid]
        if v == target {
            // 找到了
            return mid
        }
        if v < target {
            // target比中间位置的值大。
            // 如 [...,1,2,3,4,5,...], v=3, target=5。
            // 这时要向右继续找。
            // high不变,low更新为mid+1。
            low = mid+1
        } else {
            // target比中间位置的值小。
            // 如 [...1,2,3,4,5,...],v=3,target=1。
            // 这时要向左继续找。
            // low不变,high更新为mid-1。
            high = mid-1
        }
    }
    // 没找到
    return -1
}