巧妙利用二分查找:力扣1095. 山脉数组中查找目标值

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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值