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

给你一个整数数组 nums，找到峰值元素并返回其索引。数组可能包含多个峰值，在这种情况下，返回 任何一个峰值 所在位置即可。

你可以假设 nums[-1] = nums[n] = -∞ 。

你必须实现时间复杂度为 O(log 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。

提示：

1 <= nums.length <= 1000
-231 <= nums[i] <= 231 - 1
对于所有有效的 i 都有 nums[i] != nums[i + 1]
'''
from typing import List

from leetcode.tools.time import printTime


class Solution:
    @printTime()
    def findPeakElement(self, nums: List[int]) -> int:
        nums = [-float("inf")] + nums + [-float("inf")]
        n = len(nums)
        if n == 1:
            return 0
        def get(idx):
            if nums[idx] > nums[idx - 1] and nums[idx] > nums[idx + 1]:
                return 0
            if nums[idx] > nums[idx - 1] and nums[idx] < nums[idx + 1]:
                return 1
            if nums[idx] < nums[idx - 1] and nums[idx] > nums[idx + 1]:
                return 2
        left = 1
        right = n - 2
        while left < right:
            mid = (left + right) >> 1
            if get(mid) == 0:
                return mid - 1
            if get(left) == 0:
                return left - 1
            if get(right) == 0:
                return right - 1
            if get(left) == 1 and get(mid) == 2:
                right = mid
            elif get(mid) == 1 and get(right) == 2:
                left = mid
            else:
                left += 1
                right -= 1
        return 0

    @printTime()
    def _1findPeakElement(self, nums: List[int]) -> int:
        nums = nums + [-float("inf")]
        n = len(nums)
        if n == 1:
            return 0
        left = 0
        right = n - 1
        while left < right:
            mid = (left + right) >> 1
            if nums[mid] < nums[mid + 1]:
                left = mid + 1
            else:
                right = mid
        return left

nums = [1,2,1,3,5,6,4]
Solution().findPeakElement(nums)