寻找峰值,复杂一点的解法+对官方题解的理解
如果峰值存在于一个区间内,必有左端和右端单调性相反。由于没有想到官方题解 那种间接使用nums[−1]=nums[n]=−∞和间接得到峰值的方法,所以添加了几对数组首尾的边界条件。
对官方题解理解:数组首尾的单调性是已知的,左单增,右单减,所以官方题解直接利用这点,找到中点,如果此处是单减的nums[mid+1]<nums[mid],则左、中单调性相反,左、中必然存在峰值,保留中点处较大者nums[mid],因为它有可能就是峰值,此时区间缩小一半,区间首尾单调性同样是已知的,左单增,右单减。再次找到中点,如果此处是单增的nums[mid+1]>nums[mid],则中、右单调性相反,中、右必然存在峰值,保留中点处较大者nums[mid+1],因为它有可能就是峰值,此时区间又缩小一半。继续相同操作....。所有的操作都是在把区间往峰值处收缩,最后收缩到区间内只有一个元素就是峰值。
class Solution:
def findPeakElement(self , nums: List[int]) -> int:
# 含有峰值的那一段,左右单调性相反
left, right = 0, len(nums)-1 # nums[-1] = nums[n] = −∞
while left <= right:
mid = (left+right)//2
if mid-1<0 and mid+1>len(nums)-1: # 处理只有一个元素的情况
return mid
elif mid-1<0: # mid在左边界,nums[-1]=−∞,只比较右
if nums[mid]>nums[mid+1]:
return mid
elif mid+1>len(nums)-1: # mid在右边界,nums[n]=−∞,只比较左
if nums[mid]>nums[mid-1]:
return mid
else:
if nums[mid-1] < nums[mid] > nums[mid+1]: # 中间,比较左右
return mid
if left == 0: # 只考虑一边,left在左边界,只用看mid处
if nums[mid+1] - nums[mid] <0:
right = mid-1
else:
left = mid+1
else:
if (nums[mid+1] - nums[mid])*(nums[left] - nums[left-1]) < 0: # 单调性相反
right = mid-1
else:
left = mid+1