Find in Mountain Array

hard binary search mountain array array

Problem

A mountain array strictly increases to a single peak and then strictly decreases. Given such an array, return the minimum index whose value equals target, or -1 if it is absent. First binary-search for the peak, then binary-search the ascending half (prefer it for the smallest index) and, if needed, the descending half.

Inputarr = [1, 2, 3, 4, 5, 3, 1], target = 3
Output2
Value 3 appears at indices 2 and 5; the smallest index 2 lies on the ascending slope, so we return it.

def find_in_mountain_array(target, arr):
    n = len(arr)
    lo, hi = 0, n - 1
    while lo < hi:                       # locate the peak
        mid = (lo + hi) // 2
        if arr[mid] < arr[mid + 1]:
            lo = mid + 1
        else:
            hi = mid
    peak = lo
    lo, hi = 0, peak                     # ascending search
    while lo <= hi:
        mid = (lo + hi) // 2
        if arr[mid] == target:
            return mid
        if arr[mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1
    lo, hi = peak + 1, n - 1             # descending search
    while lo <= hi:
        mid = (lo + hi) // 2
        if arr[mid] == target:
            return mid
        if arr[mid] > target:
            lo = mid + 1
        else:
            hi = mid - 1
    return -1
function findInMountainArray(target, arr) {
  const n = arr.length;
  let lo = 0, hi = n - 1;
  while (lo < hi) {                      // locate the peak
    const mid = (lo + hi) >> 1;
    if (arr[mid] < arr[mid + 1]) lo = mid + 1;
    else hi = mid;
  }
  const peak = lo;
  lo = 0; hi = peak;                      // ascending search
  while (lo <= hi) {
    const mid = (lo + hi) >> 1;
    if (arr[mid] === target) return mid;
    if (arr[mid] < target) lo = mid + 1;
    else hi = mid - 1;
  }
  lo = peak + 1; hi = n - 1;              // descending search
  while (lo <= hi) {
    const mid = (lo + hi) >> 1;
    if (arr[mid] === target) return mid;
    if (arr[mid] > target) lo = mid + 1;
    else hi = mid - 1;
  }
  return -1;
}
class Solution {
    public int findInMountainArray(int target, int[] arr) {
        int n = arr.length, lo = 0, hi = n - 1;
        while (lo < hi) {                      // locate the peak
            int mid = (lo + hi) >>> 1;
            if (arr[mid] < arr[mid + 1]) lo = mid + 1;
            else hi = mid;
        }
        int peak = lo;
        lo = 0; hi = peak;                      // ascending search
        while (lo <= hi) {
            int mid = (lo + hi) >>> 1;
            if (arr[mid] == target) return mid;
            if (arr[mid] < target) lo = mid + 1;
            else hi = mid - 1;
        }
        lo = peak + 1; hi = n - 1;              // descending search
        while (lo <= hi) {
            int mid = (lo + hi) >>> 1;
            if (arr[mid] == target) return mid;
            if (arr[mid] > target) lo = mid + 1;
            else hi = mid - 1;
        }
        return -1;
    }
}
int findInMountainArray(int target, vector<int>& arr) {
    int n = arr.size(), lo = 0, hi = n - 1;
    while (lo < hi) {                      // locate the peak
        int mid = (lo + hi) / 2;
        if (arr[mid] < arr[mid + 1]) lo = mid + 1;
        else hi = mid;
    }
    int peak = lo;
    lo = 0; hi = peak;                      // ascending search
    while (lo <= hi) {
        int mid = (lo + hi) / 2;
        if (arr[mid] == target) return mid;
        if (arr[mid] < target) lo = mid + 1;
        else hi = mid - 1;
    }
    lo = peak + 1; hi = n - 1;              // descending search
    while (lo <= hi) {
        int mid = (lo + hi) / 2;
        if (arr[mid] == target) return mid;
        if (arr[mid] > target) lo = mid + 1;
        else hi = mid - 1;
    }
    return -1;
}
Time: O(log n) Space: O(1)