【LeetCode】162-寻找峰值

题目描述

峰值元素是指其值大于左右相邻值的元素。

给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。

数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。

你可以假设 nums[-1] = nums[n] = -∞

示例 1:

输入: nums = [1,2,3,1]
输出: 2
解释: 3 是峰值元素,你的函数应该返回其索引 2。

示例 2:

输入: nums = [1,2,1,3,5,6,4]
输出: 1 或 5 
解释: 你的函数可以返回索引 1,其峰值元素为 2;
     或者返回索引 5, 其峰值元素为 6。

说明:

你的解法应该是 O(logN) 时间复杂度的。


解题思路

从说明来看,要求时间复杂度是 O(logN) ,这就几乎摆明了要用二分搜索了。

但是常规的二分搜索是要搜索一个特定的,具体的元素在集合中的位置,在这一题中要找的元素并不是一个具体的值,而是一个具有某种特征(峰值)的值,如何将二分法转换一下运用到这里呢?

与传统的二分搜索设置一个mid指针不同的是,我们设置两个,mid1mid2,来保证边界的外侧总是小于边界的,这样通过边界更新,我们可以保证递归/迭代会在局部峰值处结束。

Java 实现

递归实现

public int findPeakElement (int[] nums) {
    return helper(nums, 0, nums.length - 1);
}

private int helper (int[] nums, int lo, int hi) {
    if (lo == hi) {
        return lo;
    } else {
        int mid1 = (lo + hi) / 2;
        int mid2 = mid1 + 1;
        if (nums[mid1] > nums[mid2]) {
            return helper(nums, lo, mid1);
        } else {
            return helper(nums, mid2, hi);
        }
    }
}

迭代实现

public int findPeakElement (int[] nums) {
    return helper(nums, 0, nums.length - 1);
}

private int helper (int[] nums, int lo, int hi) {

    while (lo < hi) {
        int mid1 = (lo + hi) / 2;
        int mid2 = mid1 + 1;
        if (nums[mid1] < nums[mid2]) {
            lo = mid2;
        } else {
            hi = mid1;
        }
    }
    return lo;
}

心得体会

二分搜索是根据mid1mid2的关系对搜索区域进行调整的,确保边界外侧小于边界,从而确保最后在局部峰值处结束递归/迭代。

猜你喜欢

转载自www.cnblogs.com/yuzhenzero/p/10470980.html
今日推荐