leetcode1095. 山脉数组中查找目标值-二分法

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


给你一个 山脉数组 mountainArr,请你返回能够使得 mountainArr.get(index) 等于 target 最小 的下标 index 值。

如果不存在这样的下标 index,就请返回 -1。

何为山脉数组?如果数组 A 是一个山脉数组的话,那它满足如下条件:

首先,A.length >= 3
其次,在 0 < i < A.length - 1 条件下,存在 i 使得:

  • A[0] < A[1] < … A[i-1] < A[i]
  • A[i] > A[i+1] > … > A[A.length - 1]

你将 不能直接访问该山脉数组,必须通过 MountainArray 接口来获取数据:

MountainArray.get(k) - 会返回数组中索引为k 的元素(下标从 0 开始)
MountainArray.length() - 会返回该数组的长度

注意:

对 MountainArray.get 发起超过 100 次调用的提交将被视为错误答案。此外,任何试图规避判题系统的解决方案都将会导致比赛资格被取消。

示例 1:
输入:array = [1,2,3,4,5,3,1], target = 3
输出:2
解释:3 在数组中出现了两次,下标分别为 2 和 5,我们返回最小的下标 2。

示例 2:
输入:array = [0,1,2,4,2,1], target = 3
输出:-1
解释:3 在数组中没有出现,返回 -1。

提示:
3 <= mountain_arr.length() <= 10000
0 <= target <= 10^9
0 <= mountain_arr.get(index) <= 10^9

这里面每行条件都有用,开始因为没仔细读就想复杂了。

二分法

我开始还以为可以出现[1,3,3,2,1]这种,或者[1,2,2,3,1]这种。但是题里面说了只有大于小于,想复杂了。
看着长,其实就是3次二分,第一次不太好找,后两次是一样的。


/**
 * // 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() {}
 * }
 */
 
class Solution {
    public int findInMountainArray(int target, MountainArray mountainArr) {
        int left = 0, right = mountainArr.length() - 1;
        int ll = left, rr = right;
        int top = 0;
        int ans = 0;
        while (ll <= rr) {//第一步找出山顶
            int mid = (ll + rr) >> 1;
            int midl = mid - 1, midr = mid + 1;//防止越界,因为我没做过162,完全是现想的
            if (mid - 1 >= 0) midl = mid - 1;
            if (mid + 1 < mountainArr.length()) midr = mid + 1;
            if (mountainArr.get(mid) > mountainArr.get(midl) && mountainArr.get(mid) > mountainArr.get(midr)) {
                top = mid;
                break;
            }
            if (mountainArr.get(midl) < mountainArr.get(midr)) {
                ll = mid + 1;
            } else {
                rr = mid - 1;
            }
        }
        //System.out.println("top = "+top);
        ans = binUpSearch(0,top,mountainArr,target);//先二分左边
        if (ans == -1) {
             //左边查不到在去search右边,因为升序和降序的二分有一点差别,所以重新一遍降序的
            ans = binDownSearch(top,mountainArr.length() - 1,mountainArr,target);
        }
        
        return ans;
    }
    
    public int binDownSearch(int left, int right, MountainArray mountainArr, int target) {
        if (left > right) {
            return -1;
        }
        int l = left, r = right;
        int situation = -1;
        while (l <= r) {
            int mid = (l + r) >> 1;
            int cur = mountainArr.get(mid);
            if (cur == target) {
                return mid;
            }
            if (cur < target) {
                r = mid - 1;
            } else {
                l = mid + 1;
            }
            
        }
        return -1;
    }
    public int binUpSearch(int left, int right, MountainArray mountainArr, int target) {
        if (left > right) {
            return -1;
        }
        int l = left, r = right;
        int situation = -1;
        while (l <= r) {
            int mid = (l + r) >> 1;
            int cur = mountainArr.get(mid);
            if (cur == target) {
                return mid;
            }
            if (cur < target) {
                l = mid + 1;
            } else {
                r = mid - 1;
            }
            
        }
        return -1;
    }
}

leetcode 90/100

你可能感兴趣的:(leetcode)