题目
给定一个升序整数数组,写一个函数搜索 nums 中数字 target。如果 target 存在,返回它的下标,否则返回 -1。
注意,这个数组的大小是未知的。你只可以通过 ArrayReader 接口访问这个数组,ArrayReader.get(k) 返回数组中第 k 个元素(下标从 0 开始)。
- 可以认为数组中所有的整数都小于
10000。如果你访问数组越界,ArrayReader.get会返回2147483647。
样例 1:
输入: array = [-1,0,3,5,9,12], target = 9输出: 4解释: 9 存在在 nums 中,下标为 4
样例 2:
输入: array = [-1,0,3,5,9,12], target = 2输出: -1解释: 2 不在数组中所以返回 -1
注释 :
- 可以认为数组中所有元素的值互不相同。
- 数组元素的值域是
[-9999, 9999]。
方案一(迭代)
func search(reader ArrayReader, target int) int {var i = 0for {var item = reader.get(i)if item == target {return i} else if item == 2147483647 {return -1}i += 1}}
- 时间复杂度
方案二(二分查找)
func search(reader ArrayReader, target int) int {// 特殊值处理if reader.get(0) == target {return 0}// 找到合适的 right 节点,时间复杂度 O(logn)var right = 1 // 2^right, 不能从0开始,否则左移操作就失效了for {var item = reader.get(right)if item == target {return right} else if item > target {break} else {right = right << 1 // 平方}}// 二分查找var left = 0for left <= right {var mid = (left + right) / 2var item = reader.get(mid)if item == target {return mid} else if item > target {right = mid - 1} else {left = mid + 1}}return -1}
- 时间复杂度
方案三(优化方案二)
func search(reader ArrayReader, target int) int {// 特殊值处理if reader.get(0) == target {return 0}// 找到合适的 right 节点,时间复杂度 O(logn)var left, right = 1, 1 // 2^endfor {var item = reader.get(right)if item == target {return right} else if item > target {break} else {left = rightright = right << 1 // 平方}}// 进行二分查找for left <= right {var mid = (left + right) / 2var item = reader.get(mid)if item == target {return mid} else if item > target {right = mid - 1} else {left = mid + 1}}return -1}
- 寻找 right 节点时,就固定 left 节点位置
原文
https://leetcode-cn.com/explore/learn/card/binary-search/212/template-analysis/849/
