示例1:
输入:array = [1,2,3,4,5,3,1], target = 3
输出:2
解释:3 在数组中出现了两次,下标分别为 2 和 5,我们返回最小的下标 2。
示例2:
输入:array = [0,1,2,4,2,1], target = 3
输出:-1
解释:3 在数组中没有出现,返回 -1。
二分查找
因为山脉数组由一个递增序列和一个递减序列两个单调序列组成,所以先使用二分查找找到的峰值,然后再对两个单调序列使用二分查找。就可以在O(logn)时间复杂度内找到目标值。
C++代码
/**
* // 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 {
int binarySearch(MountainArray &mountainArr, int target, int left, int right, int key(int)) {
target = key(target);
while (left <= right) {
int middle = (left + right) >> 1;
int cur = key(mountainArr.get(middle));
if (cur == target) return middle;
else if (cur < target) left = middle + 1;
else right = middle - 1;
}
return -1;
}
public:
int findInMountainArray(int target, MountainArray &mountainArr) {
int left = 0, right = mountainArr.length() - 1;
// 使用二分查找找到峰值
while (left < right) {
int middle = (left + right) >> 1;
if (mountainArr.get(middle) < mountainArr.get(middle + 1)) left = middle + 1;
else right = middle;
}
int peak = left;
int index = binarySearch(mountainArr, target, 0, peak, [](int x) -> int{return x;});
if (index != -1) {
return index;
}
return binarySearch(mountainArr, target, peak + 1, mountainArr.length() - 1, [](int x) -> int{return -x;});
}
};
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 binarySearch(self, target: int, mountain_arr: 'MountainArray', left: int, right: int, convert: 'function') -> int:
target = convert(target)
while left <= right:
mid = (left + right) >> 1
midEle = convert(mountain_arr.get(mid))
if midEle == target:
return mid
elif midEle < target:
left = mid + 1
else:
right = mid - 1
return -1
def findInMountainArray(self, target: int, mountain_arr: 'MountainArray') -> int:
arrLen = mountain_arr.length()
left = 0
right = arrLen - 1
while left < right:
mid = (left + right) >> 1;
if mountain_arr.get(mid) < mountain_arr.get(mid + 1):
left = mid + 1
else:
right = mid
peak = left
index = self.binarySearch(target, mountain_arr, 0, peak, lambda x: x)
if index != -1:
return index
return self.binarySearch(target, mountain_arr, peak + 1, arrLen - 1, lambda x: -x)