欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

leetcode(162):寻找峰值 Find Peak Element

程序员文章站 2022-06-17 18:34:53
...

leetcode(162):寻找峰值 Find Peak Element

题目

峰值元素是指其值大于左右相邻值的元素。

给定一个输入数组 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(log n)的算法。下意识想到可能是二分查找了。用二分查找,找到满足nums[i-1] < nums[i] < nums[i+1]的i即可。

由于假定了nums[-1] = nums[n] = -∞,可以认为区间[0,n)中存在一个点是极大值点,用二分法找出这个极大值点即可。假定任何情况下,lo左边的函数值小于lo点的函数值,hi点的函数值小于hi左边的函数值,令mid=(lo+hi)/2,现在要考虑迭代的条件。

1,当lo<hi时,要比较mid,mid-1,mid+1三点的函数值。mid一定是在当前区间里的,而mid+1不一定,因为mid+1可能等于hi。当mid+1=hi时,得出结论mid函数值>mid+1函数值,这个结论没有什么用,因为它既不能把lo提升到mid,也不能把hi缩小到mid。所以转而考虑mid-1的情形。

2,mid-1也不一定在当前区间中,因为可能出现mid=low,mid-1=low-1。出现这种情况时,必然有hi=lo+1。那么区间[lo,hi)中只有一个点lo,它就是要找的答案。

3,如果mid-1在当前区间中,也就存在函数值,可以用于比较。若mid-1函数值<mid函数值,则左边的区间和整个大区间性质相似,必然存在一个极值点,可以把[lo,hi)缩小到[mid,hi);否则的话,就是mid-1函数值>mid函数值,右边区间和整个区间的性质相似,必然存在一个极值点,可以把[lo,hi)缩小到[lo,mid)。

class Solution:
    def findPeakElement(self, nums: List[int]) -> int:
        if(len(nums)==0):
            return  -1
        if(len(nums) == 1):
            return 0
        lenght = len(nums)
        if(nums[0]>nums[1]):
            return  0
        elif(nums[lenght-1]>nums[lenght-2]) :
                return  lenght-1
        

        begin  = 0
        end =lenght
        while(begin<=end):
            middle = begin + (end-begin)//2
            if(nums[middle-1]<nums[middle]  and  nums[middle]>nums[middle+1] ):
                return  middle
            elif(nums[middle-1]>nums[middle] ):
                end = middle -1
            else:
                begin = middle+1