1095 find in mountain array

https://leetcode.com/problems/find-in-mountain-array/

/**
 * // 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) {
        Map<Integer, Integer> cache = new HashMap<>();
        int peak = findPeak(mountainArr, cache);
        int left = findInLeft(mountainArr, peak, target, cache);
        if (left == -1) {
            return findInRight(mountainArr, peak, target, cache);
        }
        return left;
    }
    private int findPeak(MountainArray mountainArr, Map<Integer, Integer> cache) {
        int len = mountainArr.length();
        int left = 0;
        int right = len - 1;
        while (left + 1 < right) {
            int mid = left + (right - left) / 2;
            int midVal = getFromCache(cache, mid, mountainArr);
            int leftVal = getFromCache(cache, left, mountainArr);
            int rightVal = getFromCache(cache, right, mountainArr);
            if (leftVal < midVal && midVal < rightVal) {
                left = mid;
            } else if (leftVal > midVal && midVal > rightVal) {
                right = mid;
            } else {
                left = mid;
            }
        }
        int leftVal = mountainArr.get(left);
        int rightVal = mountainArr.get(right);
        if (leftVal > rightVal) {
            return left;
        }
        return right;
    }
    private int findInLeft(MountainArray arr, int peak, int target, Map<Integer, Integer> cache) {
        int left = 0;
        int right = peak;
        while (left + 1 < right) {
            int mid = left + (right - left) / 2;
            int midVal = getFromCache(cache, mid, arr);
            int leftVal = getFromCache(cache, left, arr);
            int rightVal = getFromCache(cache, right, arr);
            
            if (midVal == target) {
                return mid;
            } 
            if (midVal < target) {
                left = mid;
            } else {
                right = mid;
            }
        }
        int leftVal = arr.get(left);
        int rightVal = arr.get(right);
        if (leftVal == target) {
            return left;
        } else if (rightVal == target) {
            return right;
        }
        return -1;
    }
    private int findInRight(MountainArray arr, int peak, int target, Map<Integer, Integer> cache) {
        int left = peak + 1;
        int right = arr.length() - 1;
        while (left + 1 < right) {
            int mid = left + (right - left) / 2;
            int midVal = getFromCache(cache, mid, arr);
            int leftVal = getFromCache(cache, left, arr);
            int rightVal = getFromCache(cache, right, arr);
            
            if (midVal == target) {
                return mid;
            } 
            if (midVal < target) {
                right = mid;
            } else {
                left = mid;
            }
        }
        int leftVal = arr.get(left);
        int rightVal = arr.get(right);
        if (leftVal == target) {
            return left;
        } else if (rightVal == target) {
            return right;
        }
        return -1;
    }
    private int getFromCache(Map<Integer, Integer> cache, int idx, MountainArray arr) {
        int val;
        if (!cache.containsKey(idx)) {
            val = arr.get(idx);
            cache.put(idx, val);
        } else {
            val = cache.get(idx);
        }
        return val;
    }
}

find peak应该有更好的办法,这里用cache有点取巧了感觉,总体思路是find peak之后在peak两边分别做二分查找,注意如果左右都有要返回左边的

private int findPeak(MountainArray mountainArr) {
        int len = mountainArr.length();
        int left = 0;
        int right = len - 1;
        while (left + 1 < right) {
            int mid = left + (right - left) / 2;
            int midVal = mountainArr.get(mid);
            int midLeftVal = mountainArr.get(mid + 1);
            
            if (midVal < midLeftVal) {
                left = mid;
            } else {
                right = mid;
            }
        }
        int leftVal = mountainArr.get(left);
        int rightVal = mountainArr.get(right);
        if (leftVal > rightVal) {
            return left;
        }
        return right;
    }

逻辑更清楚的findPeak,比较mid和mid+1的趋势,但是这个还是得用cache,不过好像大家都在用cache

Last updated