跳转至

二分查找

162.寻找峰值

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

给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。

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

你必须实现时间复杂度为 O(log n) 的算法来解决此问题。

示例 1:

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

示例 2:

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

解法一 二分法 + 递归

将数组分成区间[i, j]取中间值mid,分3种情况讨论:

  • mid 正好是峰值,直接返回
  • num[mid - 1] > num[mid],说明正在下坡,峰值一定在mid左边,递归查找区间[i, mid - 1]
  • num[mid] < num[mid + 1],说明正在上坡,峰值一定在mid右边,递归查找区间[mid + 1, j]
二分法 + 递归
  public int findPeakElement(int[] nums) {
      return peek(nums, 0, nums.length - 1);
  }

  private int peek(int[] nums, int start, int end) {
      if (start == end) {
          return start;
      } else if (start + 1 == end) {
          return nums[start] > nums[end] ? start : end;
      }
      int mid = start + (end - start) / 2;
      if (mid == 0) {
          return nums[mid] <= nums[mid + 1] ? -1 : mid;
      } else if (mid == nums.length - 1) {
          return nums[mid] > nums[mid - 1] ? mid : -1;
      } else {
          if (nums[mid - 1] < nums[mid] && nums[mid] > nums[mid + 1]) {
              return mid;
          } else if (nums[mid - 1] > nums[mid]) {
              return peek(nums, start, mid - 1);
          } else {
              return peek(nums, mid + 1, end);
          }
      }
  }