版权声明:本文为博主原创文章,未经博主允许不得转载。有事联系:[email protected] https://blog.csdn.net/qq_17550379/article/details/83780912
峰值元素是指其值大于左右相邻值的元素。
给定一个输入数组 nums
,其中 nums[i] ≠ nums[i+1]
,找到峰值元素并返回其索引。
数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞
。
示例 1:
输入: nums = [1,2,3,1]
输出: 2
解释: 3 是峰值元素,你的函数应该返回其索引 2。
示例 2:
输入: nums = [1,2,1,3,5,6,4]
输出: 1 或 5
解释: 你的函数可以返回索引 1,其峰值元素为 2;
或者返回索引 5, 其峰值元素为 6。
说明:
你的解法应该是 O(logN) 时间复杂度的。
解题思路
由于算法的时间复杂度限制,所以我们不能使用直接遍历的方法。由于时间复杂度的特殊性,所以我们首先想到的解法就是通过二分搜索法,但是这不是一个有序数组,怎么办?我们一直有一个条件没有注意nums[-1]=nums[n]=-inf
。我们可以将两端设置为端点,然后考虑中间元素。
1 2 1 3 5 6 4
i k j
此时我们应该考虑nums[k]
和nums[k+1]
的关系。如果我们nums[k]>nums[k+1]
,我们应该让j=k
,因为k
很可能就是峰值(因为右边小,而左边存在-inf
)。而如果nums[k]<nums[k+1]
,我们应该让i=k+1
,因为k+1
可能是峰值(同理)。对于nums[k]==nums[k+1]
的情况,我们放到第二种情况了考虑就可以了。最后我们要考虑边界问题,因为我们最后得到的是峰值位置,所以我们的i
和j
应该从0
和len(nums)-1
开始(我们此时要把0
和len(nums)-1
也要考虑进去,因为这两个位置也可能是峰值位置)。
class Solution:
def findPeakElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
l, r = 0, len(nums)-1
while l < r:
mid = (l + r)//2
if nums[mid] <= nums[mid+1]:
l = mid + 1
else:
r = mid
return l
最后的代码非常简洁。
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!