# 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 = 8
l = 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.