题目:162. 寻找峰值 - 力扣(LeetCode)
题目描述:
题目分析:
(1)据题知,索引-1、索引n(n为数组长度)处的元素都默认为无穷小,我们可以在一开始特判一些简单情况:当数组长度等于1时,直接返回0;当索引0处的元素大于索引1处的元素时,直接返回0;当索引n - 1处的元素大于索引n-2处的元素时,返回n - 1。
(2)如果给定的数组不满足特判条件,用折线来描述这个数组的升降,一定能找到一个峰值元素,如下图所示。
索引0到索引1是上升趋势,索引n-2到索引n-1是下降趋势,由于数组不存在重复元素,所以无论你怎么拼接这条折线,中间一定有一个峰值元素。
(3)假设我们二分到一个元素nums[m],有三种情况:1、nums[m]就是峰值元素,更新答案,退出循环;2、nums[m-1] > nums[m],这里呈下降趋势,而索引0到索引1是上升趋势,所以在0 到 m - 1这个区间肯定有一个峰值元素,right = m - 1往左侧二分;3、nums[m+1] > nums[m],这里呈上升趋势,而索引n - 2到索引n - 1是下降趋势,所以在m + 1 到 n - 2这个区间肯定有一个峰值元素,left = m + 1往右侧二分。
Code:
class Solution {public int findPeakElement(int[] nums) {int n = nums.length;//数组中只有一个元素,直接返回0if(n == 1)return 0;//索引0处的元素满足要求,返回0if(nums[0] > nums[1])return 0;//索引n - 1处的元素满足要求,返回n - 1if(nums[n - 1] > nums[n - 2])return n - 1;int left = 1,right = n - 2;int ans = 0;while(left <= right){int m = left + (right - left) / 2;//nums[m-1] > nums[m],这里是下降趋势//那么答案一定在左侧,往左侧二分if(nums[m - 1] > nums[m]){right = m - 1;}//nums[m+1] > nums[m],这里是上升趋势//答案一定在右侧,往右侧二分else if(nums[m + 1] > nums[m]){left = left + 1;}else{//nums[m+1]和nums[m-1]都不大于nums[m]//那么nums[m]就是峰值元素ans = m;break;}}return ans;}
}