http://www.lintcode.com/zh-cn/problem/search-in-a-big-sorted-array/
http://www.jiuzhang.com/solutions/search-in-a-big-sorted-array/
描述:
给一个按照升序排序的正整数数组。这个数组很大以至于你只能通过固定的接口 ArrayReader.get(k) 来访问第k个数。(或者C++里是ArrayReader->get(k)),并且你也没有办法得知这个数组有多大。找到给出的整数target第一次出现的位置。你的算法需要在O(logk)的时间复杂度内完成,k为target第一次出现的位置的下标。
如果找不到target,返回-1。
注意事项
如果你访问了 ArrayReader 中一个不可访问的下标(比如越界),ArrayReader 会返回 MAXINT = 2,147,483,647。
样例
给出 [1, 3, 6, 9, 21, ...], and target = 3, return 1.
给出 [1, 3, 6, 9, 21, ...], and target = 4, return -1.
这道题加了一个限制,就是我们不知道数组多大,那么我们就用化归的思想,看看能不能把这道题和我们做过的题关联起来。
这道题和二分法模板题目的唯一不同之处在于不知道数组大小,我们其实也不需要知道确切大小,我们可以只取这个大数组中的一部分,并且让这部分把target包括进来就可以了。
所以,这道题的思路是,先使用倍增法确定end的位置,再使用标准二分法模板求解。
倍增法:以二的幂次进行增加,换言之:1 2 4 8 16 32 64这样
"""
Definition of ArrayReader:
class ArrayReader:
def get(self, index):
# this would return the number on the given index
# return -1 if index is less than zero.
"""
class Solution:
# @param {ArrayReader} reader: An instance of ArrayReader
# @param {int} target an integer
# @return {int} an integer
def searchBigSortedArray(self, reader, target):
index = 0
while reader.get(index) < target: # 这里就是倍增法,如果当前的下标的值小于target就不断增加
index = index * 2 + 1
start, end = 0, index # 让end等于index,可以确定start到end之间一定包含了target
while start + 1 < end: # 模板求解,把下标获取值换成用get获取值就可以了
mid = (start + end) / 2
if reader.get(mid) >= target:
end = mid
else:
start = mid
if reader.get(start) == target:
return start
if reader.get(end) == target:
return end
return -1