题目描述

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

给定一个输入数组 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) 时间复杂度的。

题目解析

目让你找出一个数组中的 peak element,数组中可能存在一个或者多个 peak element,但是你只需要找出一个就好。

这道题目最直接的办法就是直接遍历一遍数组,然后将每个元素与其左右相邻的元素进行比较,符合条件输出即可。

显而易见,这么做时间复杂度是 O(n),n 为数组中元素的个数。

有没有更快的方法呢?

比 O(n) 还要快的话,一般来说只会是 O(lgn) 和 O(1)O(1)显然是不可能的,那么就只剩下 O(lgn)

通过这个时间复杂度,我相信你应该知道用什么样的算法,没错就是二分查找

那么用二分查找怎么做呢?

题目描述中有一个细节是,我们可以认为 arr[-1] == arr[n] == -Inf也就是两头的元素只需要和它相邻的一个元素比较即可。再进一步想,这里其实还隐藏了一个信息,就是我们二分查找顺着递增的方向去找的话就一定能够找到峰值

如果能够分析到这里,那么这道题基本上就算是解决了。

动画描述


参考代码

//五分钟学算法
public int findPeakElement(int[] nums) {
    if (nums == null || nums.length == 0) {
        return -1;
    }

    int start = 0, end = nums.length - 1;
    while (start + 1 < end) {
        int mid = start + (end - start) / 2;

        if (nums[mid] > nums[mid - 1] && nums[mid] > nums[mid + 1]) {
            return mid;
        } else if (nums[mid] > nums[mid - 1] && nums[mid] < nums[mid + 1]) {
            start = mid;
        } else {
            end = mid;
        }
    }

    if (nums[start] > nums[end]) {
        return start;
    }

    return end;
}


©著作权归作者所有:来自51CTO博客作者mb5fe18fab305a5的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 超详细!详解一道高频算法题:数组中的第 K 个最大元素
  2. 动画:面试必刷之二维数组中查找一个元素
  3. 前 K 个高频元素告诉你桶排序有啥用
  4. Python办公自动化|光速对比并提取两份Word/Excel中的不同元素
  5. 动画: 快速排序 | 如何求第 K 大元素?
  6. php获取数组中最后一个元素的方法
  7. php实现获取数组中相同/不相同的元素
  8. 为什么推荐使用for-each而不是for循环遍历元素?
  9. Selenium3自动化测试【12】元素定位认知

随机推荐

  1. Activity的启动流程
  2. Android 音量增加减少按钮事件
  3. android调用系统的相机服务
  4. AIDL
  5. android--------Android Studio常见问题
  6. wav格式
  7. Android Studio 修改api level
  8. android基础:动画案例(图片翻转)
  9. Android面试-基础知识
  10. javascript获取Android设备版本信息(备忘)