[3]力扣每日一题

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会取反,使得查找右面和查找左面进行的操作一致,提高代码复用
    }
};

猜你喜欢

转载自www.cnblogs.com/tsuipo/p/12806168.html