[二分法]leetcode1095:山脉数组中查找目标值(hard)

题目:

1095. 山脉数组中查找目标值

题解:

  • 三次二分法寻找山脉数组中的目标值,
  • 第一次二分:使用二分法的模板Ⅱ,寻找数组的山峰,将数组分为前半部分升序的数组和后半部分降序的数组
  • 第二次二分:在前半部分升序数组中继续使用二分法的模板Ⅱ,寻找大于等于x的最小值
  • 第三次二分:若在前半部分没有找到x,那么我们需要使用二分法的模板Ⅱ对后半部分降序数组中寻找x

代码如下:

class Solution {
public:
    //思路:三次二分查找寻找目标值的最小下标
    int findInMountainArray(int target, MountainArray &mountainArr) {
        //注意使用闭区间,如果使用开区间,在[size-1,size)时mid取左中位数,mid+1会溢出,所以我们使用闭区间
        int left=0,right=mountainArr.length()-1;

        //第一次二分,寻找山脉的山峰
        while(left<right){
            //取左中位数,因为进入循环,数组一定至少有 2 个元素
            //因此,左中位数一定有右边元素,数组下标不会发生越界
            int mid=left+((right-left)>>1);
            //mid所指的值大于等于mid+1,那么山峰在数组的左边,我们应该向左边逼近
            if(mountainArr.get(mid)>=mountainArr.get(mid+1))right=mid;
            //mid所指的值小于mid+1,那么山峰在数组的右边,我们应该向右边逼近
            else left=mid+1;
        }
        //根据题意山峰一定存在,所以我们不用特判了
        int peak=left;

        //第二次二分,在前半部分升序数组中寻找target
        left=0,right=peak;
        while(left<right){
            int mid=left+((right-left)>>1);
            if(mountainArr.get(mid)>=target)right=mid;
            else left=mid+1;
        }
        //在左边找到target,直接返回下标,否则在右半部分寻找
        if(mountainArr.get(left)==target)return left;

        //第三次二分,在后半部分降序数组中寻找target
        left=peak+1,right=mountainArr.length()-1;
        while(left<right){
            int mid=left+((right-left)>>1);
            //注意这里为<=,因为mid比x小,mid右边的元素肯定比x大,那么我们应该向左逼近
            if(mountainArr.get(mid)<=target)right=mid;
            else left=mid+1;
        }
        //在右边找到target后,直接返回下标,否则返回-1
        if(mountainArr.get(left)==target)return left;
        return -1;
    }
};
发布了486 篇原创文章 · 获赞 151 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/qq_43152052/article/details/104074701
今日推荐