162. 寻找峰值https://leetcode.cn/problems/find-peak-element/
峰值元素是指其值严格大于左右相邻值的元素。
给你一个整数数组
nums
,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。你可以假设
nums[-1] = nums[n] = -∞
。你必须实现时间复杂度为
O(log n)
的算法来解决此问题。
力扣中等难度题
首先来看题目,题中所求峰值元素为大于作用两边的元素,最简单的方法肯定是循环遍历,左右对比,最后输出坐标,但是题目条件要求时间复杂度必须为o(log n)。而我们最熟悉的该时间复杂度的算法是二分法。
二分法的使用的最大的问题是,只能用于有序的数组,而题目中却是乱序数组,该如何解决这个问题呢?
其实这道题我们可以将数组里面的各个部分分为几个有序数列的连接,而峰值就处在连接处,我们只要找到每个数组的连接处即可。而另外一个难点是,数组中的几个有序数列不一定是升序数列,而是升降混合,因此我们应当先做数列的升序降序判断。
public static int findPeakElement(int[] nums) {
int n=nums.length-1;
//先判断数组是否只有一个元素,然后判断头尾是否存在峰值元素
if(n<1||nums[0]>nums[1])return 0;
if(nums[n]>nums[n-1])return n;
int left = 0,right=n,mid;
while(true){
mid = (left+right)/2;
if(nums[mid]>nums[mid+1]){
//先判断中点是否符合
if (nums[mid]>nums[mid-1])return mid;
//如果中点不符合则可以判断此段为降序数列,则可知峰值元素在mid左侧
//将right左移
else right = mid;
}
if(nums[mid]<nums[mid+1]){
//判断是否为最低点,是的话则将right左移
if (nums[mid]<nums[mid-1])right = mid;
//不为最低点的话则可知此为升序数列,将left右移
else left = mid;
}
}
}