原题出处:https://leetcode.cn/leetbook/read/top-interview-questions-medium/xv4bbv/
解法一:
class Solution {
public int findPeakElement(int[] nums) {
return getResult(nums,0);
}
private int getResult(int[] nums,int index) {
int firstValue = index == 0 ? Integer.MIN_VALUE : nums[index-1];
int mid = nums[index];
int lastValue = index == nums.length -1 ? Integer.MIN_VALUE : nums[index+1];
if (firstValue < mid && mid > lastValue) {
return index;
}
if (index == nums.length -1) {
return 0;
}
return getResult(nums,index +1);
}
}
思路:递归,我们定义三个变量,然后对比这三个变量,只需要中间的元素,大于第一个变量,小于第三个变量,那我们就把它的索引值返回即可,否则就将索引值加1进行递归。
解法二:
class Solution {
public int findPeakElement(int[] nums) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if ((mid == 0 || nums[mid] > nums[mid - 1]) &&
(mid == nums.length - 1 || nums[mid] > nums[mid + 1])) {
return mid;
} else if (mid > 0 && nums[mid - 1] > nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return -1;
}
}
思路:
题目要求时间复杂度为 O(log n),因此可以考虑使用二分查找来解决。具体思路如下:
-
初始化左右指针 left 和 right 分别指向数组的第一个元素和最后一个元素。
-
进入循环,当 left 小于等于 right 时执行以下操作:
-
计算中间位置 mid = (left + right) // 2。
-
如果 mid 处于上升趋势,则峰值可能在 mid 右侧,因此将 left 更新为 mid + 1。
-
如果 mid 处于下降趋势,则峰值可能在 mid 左侧,因此将 right 更新为 mid - 1。
-
否则 mid 就是峰值,直接返回 mid。
-
如果循环结束仍未找到峰值,返回 -1。