A peak element is an element that is strictly greater than its neighbors.
Given an integer array nums, find a peak element, and return its index. If the array contains multiple peaks, return the index to any of the peaks.
You may imagine that nums[-1] = nums[n] = -∞.
You must write an algorithm that runs in O(log n) time.
Example 1:
Input: nums = [1,2,3,1] Output: 2 Explanation: 3 is a peak element and your function should return the index number 2.
Example 2:
Input: nums = [1,2,1,3,5,6,4] Output: 5 Explanation: Your function can return either index number 1 where the peak element is 2, or index number 5 where the peak element is 6.
Constraints:
1 <= nums.length <= 1000-231 <= nums[i] <= 231 - 1nums[i] != nums[i + 1]for all validi.
题目大意是给定一个数组,从中找出一个峰值(该值比左边和右边的数都要大),要 求算法时间复杂度为O(logn)。显然是要我们用二分查找法(Binary Search)。首先还是要把握住二分查找法的核心思想,把数组从中间分成两个区间后用什么条件可以判断目标数落在哪个区间。
我们先来看数组两个特例:
1)数组是单调递增的,数组的每个数都比右边的小,那峰值就是最后的那个数。
2)数组是单调递减的,数组的每个数都比右边的大,那峰值就是第一个数。
可以看出无论如何数组(数组里没有重复值)都至少含有一个峰值。那把数组从中间分成两个区间后,有没办法判断哪个区间一定存在一个峰值呢?
1)如果中间值比左边邻居值小,即nums[mid] < nums[mid - 1] (mid > 0),这种情况左半区间有两种可能,单调递减或非单调。无论哪种可能左半区间都一定有至少一个峰值。
2)如果中间值比左边邻居值大,即nums[mid] > nums[mid - 1] (mid > 0),这种情况右半区间(从nums[mid]开始到结束)有两种可能,单调递增或非单调。无论哪种可能右半区间都一定有至少一个峰值。
注:对于mid == 0的情况,可以归为上述情况2即右半区间一定有峰值。
判断条件都确定了,代码实现就相当的简单了。
class Solution:
def findPeakElement(self, nums: List[int]) -> int:
l, r = 0, len(nums) - 1
while l <= r:
mid = l + (r - l) // 2
if mid > 0 and nums[mid] < nums[mid - 1]:
r = mid - 1
else :
l = mid + 1
return l - 1

这篇博客介绍了如何解决LeetCode 162题,即寻找峰值元素。峰值元素是大于其相邻元素的元素。通过分析数组特性,特别是单调性的变化,提出使用二分查找法在O(logn)的时间复杂度内找到峰值元素。当数组单调递增时,峰值是最后一个元素;单调递减时,峰值是第一个元素。根据中间元素与左侧元素的关系,可以确定峰值所在的区间,从而简化问题。博客提供了详细的逻辑分析和简洁的代码实现。
系列题5&spm=1001.2101.3001.5002&articleId=122006587&d=1&t=3&u=aec66b056a53459b962a05e5ffb7a368)

被折叠的 条评论
为什么被折叠?



