Loading problems...
TL;DR: We solve this by first locating the peak element's index using binary search, then performing two separate binary searches on the ascending and descending slopes to find the target.
The Find in Mountain Array problem asks us to search for a specific target value within a "mountain array." A mountain array is defined as an array that strictly increases to a peak element and then strictly decreases. We are not given direct access to the array; instead, we must interact with it via a MountainArray interface that allows us to retrieve the length and the value at a specific index.
The critical constraint in LeetCode 1095 is the limit on API calls: we are allowed a maximum of 100 calls to get(k). Since the array length can be up to 10,000, a linear scan is impossible, necessitating a logarithmic time complexity solution.
The most straightforward approach to finding an element in an array is a linear scan. We would simply iterate through every index from 0 to n-1, call get(i), and check if the value equals the .
targetNaive Pseudo-code:
textfunction findInMountainArray(target, mountainArr): length = mountainArr.length() for i from 0 to length - 1: val = mountainArr.get(i) if val == target: return i return -1
Complexity Analysis:
Why it fails:
The problem strictly enforces an interaction limit. With up to , a linear scan requires up to 10,000 calls to MountainArray.get(). The limit is 100 calls. Since , this approach will immediately trigger a "Wrong Answer" or disqualification due to excessive API usage. We must minimize calls using an strategy.
The core difficulty in LeetCode 1095 is that the entire array is not sorted in a single direction. Standard binary search requires monotonic data (always increasing or always decreasing). A mountain array is bitonic: it increases, reaches a peak, and then decreases.
However, the peak element acts as a boundary.
If we can identify the index of the peak, we can treat the problem as two independent binary search problems on sorted arrays.
To find the peak efficiently, we utilize the derivative (slope) logic used in finding extrema. By comparing mid and mid + 1, we can determine if we are on the ascending slope or the descending slope:
arr[mid] < arr[mid + 1], we are climbing up; the peak is to the right.arr[mid] > arr[mid + 1], we are climbing down (or at the peak); the actual peak is at mid or to the left.Visual Description: Imagine plotting the array values on a graph where the Y-axis is the value and X-axis is the index. The shape forms an inverted "V".

Let's trace the algorithm with mountainArr = [1, 2, 3, 4, 5, 3, 1] and target = 3.
Step 1: Find Peak Index
[0, 6]. mid = 3.arr[3] (4) and arr[4] (5).[4, 6].mid = 5. Compare arr[5] (3) and arr[6] (1).[4, 5].mid = 4. Compare arr[4] (5) and arr[5] (3).[4, 4].low == high. Peak Index is 4 (Value is 5).Step 2: Search Left (Ascending) [0, 4]
[0, 4]. Target is 3.mid = 2. arr[2] is 3.2.Note: If the target were 3 in the right half only (e.g., if the array were [1, 5, 3]), Step 2 would fail, and we would proceed to Step 3.
The correctness relies on the Bitonic Property of the Mountain Array.
arr[i] < arr[i+1] is true for all and false for all . This monotonicity in the slope allows binary search to converge on the peak index correctly.[0, peak] is strictly increasing, and the right side [peak+1, end] is strictly decreasing.cpp/** * // This is the MountainArray's API interface. * // You should not implement it, or speculate about its implementation * class MountainArray { * public: * int get(int index); * int length(); * }; */ class Solution { public: int findInMountainArray(int target, MountainArray &mountainArr) { int n = mountainArr.length(); // 1. Find the peak index int low = 0; int high = n - 1; while (low < high) { int mid = low + (high - low) / 2; if (mountainArr.get(mid) < mountainArr.get(mid + 1)) { // Ascending part, peak is to the right low = mid + 1; } else { // Descending part or peak, peak is left or here high = mid; } } int peakIndex = low; // 2. Search in the ascending part (left of peak) low = 0; high = peakIndex; while (low <= high) { int mid = low + (high - low) / 2; int val = mountainArr.get(mid); if (val == target) return mid; if (val < target) { low = mid + 1; } else { high = mid - 1; } } // 3. Search in the descending part (right of peak) low = peakIndex + 1; high = n - 1; while (low <= high) { int mid = low + (high - low) / 2; int val = mountainArr.get(mid); if (val == target) return mid; if (val < target) { // In descending order, smaller value means we are too far right high = mid - 1; } else { // Larger value means we are too far left low = mid + 1; } } return -1; } };
java/** * // 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 length = mountainArr.length(); // 1. Find the peak index int low = 0; int high = length - 1; while (low < high) { int mid = low + (high - low) / 2; if (mountainArr.get(mid) < mountainArr.get(mid + 1)) { // We are in the increasing section low = mid + 1; } else { // We are in the decreasing section or at the peak high = mid; } } int peakIndex = low; // 2. Binary Search on the increasing subarray [0, peakIndex] int result = binarySearch(mountainArr, target, 0, peakIndex, true); if (result != -1) { return result; } // 3. Binary Search on the decreasing subarray [peakIndex + 1, length - 1] return binarySearch(mountainArr, target, peakIndex + 1, length - 1, false); } private int binarySearch(MountainArray arr, int target, int low, int high, boolean ascending) { while (low <= high) { int mid = low + (high - low) / 2; int val = arr.get(mid); if (val == target) { return mid; } if (ascending) { if (val < target) { low = mid + 1; } else { high = mid - 1; } } else { // Descending logic if (val < target) { high = mid - 1; // Target is larger, move left } else { low = mid + 1; // Target is smaller, move right } } } return -1; } }
python# """ # This is MountainArray's API interface. # You should not implement it, or speculate about its implementation # """ #class MountainArray: # def get(self, index: int) -> int: # def length(self) -> int: class Solution: def findInMountainArray(self, target: int, mountain_arr: 'MountainArray') -> int: n = mountain_arr.length() # 1. Find the peak index low, high = 0, n - 1 while low < high: mid = (low + high) // 2 if mountain_arr.get(mid) < mountain_arr.get(mid + 1): low = mid + 1 else: high = mid peak_index = low # 2. Search in the ascending part low, high = 0, peak_index while low <= high: mid = (low + high) // 2 val = mountain_arr.get(mid) if val == target: return mid elif val < target: low = mid + 1 else: high = mid - 1 # 3. Search in the descending part low, high = peak_index + 1, n - 1 while low <= high: mid = (low + high) // 2 val = mountain_arr.get(mid) if val == target: return mid elif val < target: # In descending, smaller value means go left (to larger values) high = mid - 1 else: low = mid + 1 return -1
Time Complexity:
Space Complexity:
low, high, mid, peak) and values. No recursion stack or auxiliary data structures are needed if implemented iteratively.The logic used in Find in Mountain Array is a specific application of binary search on modified sorted arrays. This pattern recurs in several famous interview questions:
Why does the naive linear scan fail?
The naive solution fails because the problem imposes a hard limit of 100 calls to get(). A linear scan requires calls. Since can be up to 10,000, this drastically exceeds the limit, resulting in a Time Limit Exceeded or Wrong Answer verdict.
Mistake 1: Not handling the descending order correctly.
val < target means ) to the right side of the mountain.low = mid + 1Mistake 2: Caching the peak value but not the index.
[0, peakIndex] and [peakIndex + 1, end].Mistake 3: Infinite loops during peak finding.
high = mid - 1 or low = mid incorrectly without adjusting the loop condition or mid calculation.low and high are adjacent, mid might calculate to low, and if the logic doesn't advance pointers, the loop never terminates.