# This is the Leetcode interface for MountainArray:
# class MountainArray:
# def get(self, index: int) -> int:
# def length(self) -> int:
class Solution:
def findInMountainArray(self, target: int, mountain_arr: 'MountainArray') -> int:
def find_peak():
l, r = 0, mountain_arr.length() - 1
while l < r:
m = (l + r) // 2
if mountain_arr.get(m) < mountain_arr.get(m + 1):
l = m + 1
else:
r = m
return l
def binary_search(l, r, target, asc=True):
while l <= r:
m = (l + r) // 2
val = mountain_arr.get(m)
if val == target:
return m
if asc:
if val < target:
l = m + 1
else:
r = m - 1
else:
if val > target:
l = m + 1
else:
r = m - 1
return -1
peak = find_peak()
# Search in ascending part
idx = binary_search(0, peak, target, asc=True)
if idx != -1:
return idx
# Search in descending part
return binary_search(peak+1, mountain_arr.length()-1, target, asc=False)
/**
* // 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();
// Find peak
int l = 0, r = n - 1;
while (l < r) {
int m = (l + r) / 2;
if (mountainArr.get(m) < mountainArr.get(m + 1))
l = m + 1;
else
r = m;
}
int peak = l;
// Binary search ascending
int left = 0, right = peak;
while (left <= right) {
int m = (left + right) / 2;
int val = mountainArr.get(m);
if (val == target)
return m;
else if (val < target)
left = m + 1;
else
right = m - 1;
}
// Binary search descending
left = peak + 1, right = n - 1;
while (left <= right) {
int m = (left + right) / 2;
int val = mountainArr.get(m);
if (val == target)
return m;
else if (val > target)
left = m + 1;
else
right = m - 1;
}
return -1;
}
};
/**
* // This is the 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 n = mountainArr.length();
// Find peak
int l = 0, r = n - 1;
while (l < r) {
int m = (l + r) / 2;
if (mountainArr.get(m) < mountainArr.get(m + 1))
l = m + 1;
else
r = m;
}
int peak = l;
// Binary search ascending
int left = 0, right = peak;
while (left <= right) {
int m = (left + right) / 2;
int val = mountainArr.get(m);
if (val == target)
return m;
else if (val < target)
left = m + 1;
else
right = m - 1;
}
// Binary search descending
left = peak + 1;
right = n - 1;
while (left <= right) {
int m = (left + right) / 2;
int val = mountainArr.get(m);
if (val == target)
return m;
else if (val > target)
left = m + 1;
else
right = m - 1;
}
return -1;
}
}
/**
* // This is the MountainArray's API interface.
* // You should not implement it, or speculate about its implementation
* function MountainArray() {
* @return {number}
* this.get = function(index) {
* ...
* };
* @return {number}
* this.length = function() {
* ...
* };
* }
*/
var findInMountainArray = function(target, mountainArr) {
function findPeak() {
let l = 0, r = mountainArr.length() - 1;
while (l < r) {
const m = Math.floor((l + r) / 2);
if (mountainArr.get(m) < mountainArr.get(m + 1)) {
l = m + 1;
} else {
r = m;
}
}
return l;
}
function binarySearch(l, r, target, asc = true) {
while (l <= r) {
const m = Math.floor((l + r) / 2);
const val = mountainArr.get(m);
if (val === target) return m;
if (asc) {
if (val < target) l = m + 1;
else r = m - 1;
} else {
if (val > target) l = m + 1;
else r = m - 1;
}
}
return -1;
}
const peak = findPeak();
let idx = binarySearch(0, peak, target, true);
if (idx !== -1) return idx;
return binarySearch(peak + 1, mountainArr.length() - 1, target, false);
};
target value. You have access only through a special interface, MountainArray, which provides get(index) and length() methods. The goal is to return the smallest index where mountainArr.get(index) == target, or -1 if the target does not exist in the array.get() and length().get() calls.get() to see if it matches the target. However, this would be inefficient, especially given the constraints on the number of calls to get().get() calls.
get(mid) and get(mid + 1):
get(mid) < get(mid + 1), the peak is to the right, so move the left boundary to mid + 1.mid or to the left, so move the right boundary to mid.0 to peak (inclusive). Since this part is sorted in ascending order, use standard binary search:
get(mid) == target, return mid.get(mid) < target, move left to mid + 1.mid - 1.peak + 1 to length - 1. This part is sorted in descending order, so reverse the comparison:
get(mid) == target, return mid.get(mid) > target, move left to mid + 1.mid - 1.-1.O(log n) get() calls for each search, which is efficient and meets the problem's constraints.
mountainArr = [1, 5, 9, 12, 8, 4, 2], target = 8l = 0, r = 6.mid = 3, get(3) = 12, get(4) = 8 → 12 > 8, so peak is at or before 3. Set r = 3.l = 0, r = 3; mid = 1, get(1) = 5, get(2) = 9 → 5 < 9, so peak is after 1. Set l = 2.l = 2, r = 3; mid = 2, get(2) = 9, get(3) = 12 → 9 < 12, so peak is after 2. Set l = 3.l = r = 3, so the peak is at index 3 (12).
l = 0, r = 3; mid = 1, get(1) = 5 < 8, so l = 2.l = 2, r = 3; mid = 2, get(2) = 9 > 8, so r = 1.l = 4, r = 6; mid = 5, get(5) = 4 < 8, so (descending) r = 4.l = 4, r = 4; mid = 4, get(4) = 8 == 8, found at index 4.4 (the index of 8).
O(n) (you would check every element with get() up to n times).O(1) (no extra space needed).O(log n) for peak-finding + O(log n) for each binary search = O(log n) overall.O(1) (no extra space used).get() calls.