上期回顾:
超全的二分查找汇总:https://blog.csdn.net/qq_19446965/article/details/82184672
其余练习题1:https://www.cnblogs.com/rnanprince/p/11743414.html
其余练习题2:https://www.cnblogs.com/rnanprince/p/11761940.html
倍增法步骤:
- 初始化:
index = 0
开始,jump = 1
为向后跳跃的长度; - 循环:将 index 向后移动
jump
个元素, 并将jump
翻倍; - 如果移动后的位置>=
target
, 则jump
缩小至一半,进行更小步的跳跃; - 终止的条件:
jump == 0,
这时 index+ 1
的位置已经不小于target
了 (index 位置的仍然是小于target,即 最大的小于target
的元素); - 最后,判断一下 index
+ 1
是否与target
相等。
【例题】
在大数组中查找 Search in a Big Sorted Array
给一个按照升序排序的非负整数数组。这个数组很大以至于你只能通过固定的接口 ArrayReader.get(k)
来访问第k个数(或者C++里是ArrayReader->get(k)),并且你也没有办法得知这个数组有多大。
找到给出的整数target第一次出现的位置。你的算法需要在O(logk)的时间复杂度内完成,k为target第一次出现的位置的下标。
如果找不到target,返回-1。
来自:https://www.jiuzhang.com/solutions/search-in-a-big-sorted-array/#tag-highlight-lang-python
1、倍增法
def search(reader, target):
if reader.get(0) > target:
return -1
index = 0
jump = 1
while jump: # 当jump为0时, 跳出循环
while jump and reader.get(index + jump) >= target:
jump >>= 1
index += jump
jump <<= 1
if reader.get(index + 1) == target:
return index + 1
else:
return -1
2、二分法
def search(reader, target):
left = 0
right = 1
while reader.get(right) < target:
right *= 2
# 以下严格按照模板查找
while left + 1 < right:
mid = left + (right - left) //2
if target > reader.get(mid):
left = mid
else:
right= mid
if reader.get(left) == target:
return left
if reader.get(right) == target:
return right
return -1