Note, one condition simplifies the solution

  1. any peak element, can be local peak or global peak

time O(N) space O(1)

class Solution:
    def findPeakElement(self, nums: List[int]) -> int:
        """
        Below are four cases 

        \     \    /   /\     \          
         \     \  /   /  \     \
          \     \/   /    \     \
        
        """
        n = len(nums)
        
        for i in range(n-1):
            if nums[i] > nums[i+1]:
                return i
        return n-1 

optimal: Binary Search + recursive


class Solution:
# time O(lgN) space(lgN)
    def findPeakElement(self, nums: List[int]) -> int:
        n = len(nums)
        def bs(l,r,nums):
            # there is only one candidate element left  
            if l == r:
                return l
            # there assumes there are at least 2 elements ,so mid+1 not overflow 
            mid = l + (r-l)//2
            if nums[mid] > nums[mid+1]:
                return bs(l,mid,nums)
            return bs(mid+1,r,nums)
        
        
        return bs(0,n-1,nums)

optimal space: time O(lgN) space O(1)

class Solution:
    def findPeakElement(self, nums: List[int]) -> int:
        n = len(nums)
        l,r = 0,n-1
        while l < r:# there are at least 2 elements
            mid = l + (r-l)//2
            if nums[mid] > nums[mid+1]:
                r = mid
            else:
                l = mid +1 
        return r