LeetCode每日一题

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


给你一个山脉数组mountainArr请你返回能够使得mountainArr.get(index)等于target 最小的下标index值。
如果不存在这样的下标index就请返回 -1。
链接: https://leetcode-cn.com/problems/find-in-mountain-array.

在写这道题时,我们首先需要得知什么是山脉数组(解释在leetcode上已经解释的十分清楚了)。
如果数组A是山脉数组,则其满足一下条件:

  1. A.length >= 3
  2. 在 0 < i < A.length - 1 条件下,存在 i 使得:
    A[0] < A[1] < … A[i-1] < A[i]
    A[i] > A[i+1] > … > A[A.length - 1]

再得知什么是山脉数组以后,我们就可以对这道题进行求解了。并且要注意的是题目要求我们求得的是最小的下标值。

这道题目主要考察的是对二分查找的理解,本题思路可以分为三个步骤:

  1. 首先找到数组中的最大的值
  2. 在数组左边—最大值之间寻找target
  3. 若未在左边找到值,则我们需要在最大值—右边寻找target

在了解解题思路以后,我们就可以完全套用二分查找的模板了。

//二分查找模板
//使用二分查找的前提是该数组是排过序的,即数组是有序的
public int binarySearch(int target, int[] arr, int left, int right){
	while(left <= right){
		int mid = left + ((right - left) >> 1); //这样写可以防止left + right 溢出
		if(arr[mid] == target) return mid;
		else if(arr[mid] < target)  //如果中间值 < target, 我们需要在左边查找
			left = mid - 1;
		else   //如果中间值 > target, 我们需要在右边查找
			right = mid + 1; 
	}
	//最后没有找到的话返回-1
	return -1;
}

通过模板,我们可以写出这道题的代码,不过二分查找的考察点并不是代码,而是需要仔细考虑边界条件。

/**
 * // This is MountainArray's API interface.
 * // You should not implement it, or speculate about its implementation
 * interface MountainArray {
 *     public int get(int index) {}
 *     public int length() {}
 * }
 */
public int findInMountainArray(int target, MountainArray mountainArr) {
        int size = mountainArr.length();
        //首先找到制高点
        int i = findMountainTop(mountainArr, 0, size - 1);
        int res = -1;
        //左边---制高点  找target
        res = findMountainLeft(target, mountainArr, 0, i);
        if(res != -1) return res;
        //制高点---右边  找target
        res = findMountainRight(target, mountainArr, i + 1, size - 1);
        return res;
    }

    public int findMountainTop(MountainArray mountainArr, int left, int right){
        while(left <= right){
            int mid = left + ((right - left) >> 1);
            if(mountainArr.get(mid) < mountainArr.get(mid + 1)){
                left = mid + 1;
            }else{
                right = mid - 1;
        }
        //此处返回left是根据上面的判断条件,如果
        //mountainArr.get(mid) > mountainArr.get(mid + 1),则左边的一定是最大值
        return left;
    }

    public int findMountainLeft(int target, MountainArray mountainArr, int left, int right){
    //这里写left <= right的原因是考虑到数组中只有一个元素的情况,当然也可以写left < right
    //不过下面的判断条件需要仔细考虑一下边界条件
        while(left <= right){
            int mid = left + ((right - left) >> 1);
            if(mountainArr.get(mid) == target) return mid;
            else if(mountainArr.get(mid) < target){
                left = mid + 1;
            }else
                right = mid - 1;
        }
        return -1;
    }

    public int findMountainRight(int target, MountainArray mountainArr, int left, int right){
        while(left <= right){
            int mid = left + ((right - left) >> 1);
            if(mountainArr.get(mid) == target) return mid;
            else if(mountainArr.get(mid) < target){
            //这里需要注意的是山脉数组右半部分左边的值 > 右边的值
                right = mid - 1;
            }else
                left = mid + 1;
        }
        return -1;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值