2020.4.29山脉数组中查找目标值
题目呈现如下:
思路介绍:
本题是二分查找的一个变体.首先明确一个观点,凡是有序的一串数据都可以采用二分查找.
我的理解是:有序的其实意思是指,知道通过mid挖掘到的信息,能够推断出下一步查找的方向,并且这个方向是可以缩小问题规模的.
本题的山脉数组即有一个或者若干个峰值,峰值左侧非降序,右侧非增序.所以我们算法的分为以下两步:
- 1.二分法找到峰值
- 2.峰值左侧和右侧分别运用二分查找,查找到target的下标,如果没有则返回-1.
- 3.比较左右的返回值,若不都为-1则返回较小那个;都为-1则返回-1说明未查找到.
下附AC代码
// 借鉴官方AC答案,运用匿名函数将原本左右查询两个函数合并成了一个函数
// 正数递减,若全部取反则可看作是递增
class Solution {
int binarySearch(MountainArray &mountain, int l, int r, int target, int negOrPos(int)) {
target = negOrPos(target);
while (l <= r) {
int mid = (l + r) / 2;
int cur = negOrPos(mountain.get(mid));
if (cur == target)
return mid;
else if (cur > target)
r = mid - 1;
else l = mid + 1;
}
return -1;
}
public:
int findInMountainArray(int target, MountainArray &mountainArr) {
int l = 0, r = mountainArr.length() - 1;
while (l < r) {
int mid = (l + r) / 2;
if (mountainArr.get(mid) < mountainArr.get(mid + 1))
l = mid + 1; // 往右找peak
else r = mid;
}
int peak = l;
int index = binarySearch(mountainArr, 0, peak, target, [](int x) -> int{return x;}); // 传入lambda函数,negOrPos,不取反
if (index != -1) return index;
return binarySearch(mountainArr, peak + 1, mountainArr.length() - 1, target, [](int x) -> int{return -x;}); // negOrPos会取反,使得查找右面和查找左面进行的操作一致,提高代码复用
}
};