1、题目描述:
2、题解:
二分查找
思路:
对于山脉数组,可以看成两部分:前有序数组、后有序数组,分别是升序和降序有序
可以分为三步:
1、找山顶元素mountaintop(也就是最大值)的索引
2、在前有序数组中查找target所在的索引,找到返回,没找到再执行第三步
3、在后有序数组中查找target所在的索引
每一步都是二分查找
Python代码如下:
# """
# This is MountainArray's API interface.
# You should not implement it, or speculate about its implementation
# """
#class MountainArray:
# def get(self, index: int) -> int:
# def length(self) -> int:
class Solution:
def findInMountainArray(self, target: int, mountain_arr: 'MountainArray') -> int:
#二分查找
size = mountain_arr.length()
mountaintop = self.findMountaintop(mountain_arr,0,size-1)
res = self.findPreArr(mountain_arr,0,mountaintop,target)
if res != -1:
return res
return self.findFormArr(mountain_arr,mountaintop+1,size-1,target)
def findMountaintop(self,mountain_arr,left,right):
while left < right:
mid = left + (right - left) // 2
if mountain_arr.get(mid) < mountain_arr.get(mid+1):
left = mid + 1
else:
right = mid
return left
def findPreArr(self,mountain_arr,left,right,target):
while left < right:
mid = left + (right - left) // 2
if mountain_arr.get(mid) < target:
left = mid + 1
else:
right = mid
if mountain_arr.get(left) == target:
return left
else:
return -1
def findFormArr(self,mountain_arr,left,right,target):
while left < right:
mid = left + (right - left) // 2
if mountain_arr.get(mid) > target:
left = mid + 1
else:
right = mid
if mountain_arr.get(left) == target:
return left
else:
return -1
或者
class Solution:
def findInMountainArray(self, target: int, mountain_arr: 'MountainArray') -> int:
#二分查找
size = mountain_arr.length()
mountaintop = self.findMountaintop(mountain_arr,0,size-1)
res = self.findPreArr(mountain_arr,0,mountaintop,target)
if res != -1:
return res
return self.findFormArr(mountain_arr,mountaintop+1,size-1,target)
def findMountaintop(self,mountain_arr,left,right):
while left < right:
mid = left + (right - left) // 2
if mountain_arr.get(mid) < mountain_arr.get(mid+1):
left = mid + 1
else:
right = mid
return left
def findPreArr(self,mountain_arr,left,right,target):
while left <= right:
mid = left + (right - left) // 2
temp = mountain_arr.get(mid)
if temp < target:
left = mid + 1
elif temp > target:
right = mid - 1
elif temp == target:
return mid
return -1
def findFormArr(self,mountain_arr,left,right,target):
while left <= right:
mid = left + (right - left) // 2
temp = mountain_arr.get(mid)
if temp < target:
right = mid - 1
elif temp > target:
left = mid + 1
elif temp == target:
return mid
return -1
发现在第二步和第三步使用二分查找时,函数体差不多,我们考虑整合成一个函数
python代码如下:
class Solution:
def findInMountainArray(self, target: int, mountain_arr: 'MountainArray') -> int:
#二分查找
size = mountain_arr.length()
#寻找山顶的索引
left ,right = 0,size-1
while left < right:
mid = left + (right - left) // 2
if mountain_arr.get(mid) < mountain_arr.get(mid + 1):
left = mid + 1
else:
right = mid
mountaintop = left
#在左有序数组中查找
res = self.binary_search(mountain_arr,0,mountaintop,target)
if res != -1:
return res
#在右有序数组中查找
return self.binary_search(mountain_arr,mountaintop+1,size-1,target,lambda x : -x)
def binary_search(self,mountain_arr,left,right,target,key = lambda x : x):
target = key(target)
while left <= right:
mid = left + (right - left) // 2
temp = key(mountain_arr.get(mid))
if temp < target:
left = mid + 1
elif temp > target:
right = mid - 1
elif temp == target:
return mid
return -1
3、复杂度分析:
时间复杂度:O(logN)
空间复杂度:O(1)