一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第24天,点击查看活动详情。
前言
力扣第162题 寻找峰值 如下所示:
一、思路
题目的意思很简单,找到数组中的某一个峰值,满足 nums[i] > nums[i-1] 且 nums[i] < nums[i+1]。此外提示中还有两个重要的信息:
nums[i] != nums[i+1],也就是说相邻的两个元素是不相等的。nums[-1] = nums[n] = -∞
既然要找到数组的峰值,一个非常简单朴素的想法为:一次遍历数组中的所有元素,如果某个元素 nums[i] 满足条件则返回该下标 i。但是这样的时间复杂度为 O(N),不能满足题目中时间复杂度 O(logN)。
说道时间复杂度 O(logN),很容易就能联想到使用 二分法。我们不妨假设某次二分后左右边界内的数组如下所示:
nums[mid] 会有如下的三种情况
nums[mid]在上升区间
此时出现了 nums[mid+1] > nums[mid],出现了上升的趋势,在 mid 的右边一定会出现峰顶。所以丢弃mid靠左的元素即可,即 left = mid+1
提示:即使
mid往后都是升序的,也会在n-1出现峰顶。因为nums[n]为负无穷
nums[mid]在下降区间
此时出现了 nums[mid+1] < nums[mid],出现了上升的趋势,在 mid 的左边一定会出现峰顶。所以丢弃mid靠右的元素即可,即 right = mid(mid下标不能丢弃)
nums[mid]在峰顶,此时直接返回结果即可
综上所述,二分法 的思路为:如 mid 处于上升期则丢弃左边,如mid 处于下降期则丢弃右边
二、实现
实现代码
实现代码与思路中保持一致
public int findPeakElement(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = (left + right) / 2;
if(nums[mid] < nums[mid + 1]){
left = mid + 1;
}else{
right = mid;
}
}
return left;
}
测试代码
public static void main(String[] args) {
int[] nums = {1,2,1,3,5,6,4};
new Number162().findPeakElement(nums);
}
结果
三、总结
感谢看到最后,非常荣幸能够帮助到你~♥
如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~