【LeetCode 二分查找专项】山脉数组的峰顶索引(852)

1. 题目

符合下列属性的数组 arr 称为山脉数组

  • arr.length >= 3
  • 存在 i0 < i < arr.length - 1)使得:
    • arr[0] < arr[1] < ... arr[i-1] < arr[i]
    • arr[i] > arr[i+1] > ... > arr[arr.length - 1]

给你由整数组成的山脉数组 arr ,返回任何满足 arr[0] < arr[1] < ... arr[i - 1] < arr[i] > arr[i + 1] > ... > arr[arr.length - 1] 的下标 i

1.1 示例

  • 示例 1 1 1
  • 输入: arr = [0, 1, 0]
  • 输出: 1 1 1
  • 示例 2 2 2
  • 输入: arr = [0, 2, 1, 0]
  • 输出: 1 1 1
  • 示例 3 3 3
  • 输入: arr = [0, 10, 5, 2]
  • 输出: 1 1 1
  • 示例 4 4 4
  • 输入: arr = [3, 4, 5, 1]
  • 输出: 2 2 2
  • 示例 5 5 5
  • 输入: arr = [24, 69, 100, 99, 79, 78, 67, 36, 26, 19]
  • 输出: 2 2 2

1.2 说明

1.3 提示

  • 3 ≤ a r r . l e n g t h ≤ 1 0 4 3 \le arr.length \le 10^4 3arr.length104
  • 0 ≤ a r r [ i ] ≤ 1 0 6 0 \le arr[i] \le 10^6 0arr[i]106
  • 题目数据保证 arr 是一个山脉数组

1.4 进阶

很容易想到时间复杂度 O ( n ) O(n) O(n) 的解决方案,你可以设计一个 O ( l o g ( n ) ) O(log(n)) O(log(n)) 的解决方案吗?

2. 解法一

2.1 分析

略。

2.2 解答

from typing import List


class Solution:
    def peak_index_in_mountain_array(self, arr: List[int]) -> int:
        left, right = 0, len(arr) - 1
        while left <= right - 2:
            mid = left + (right - left) // 2
            if arr[mid - 1] < arr[mid] > arr[mid + 1]:
                return mid
            elif arr[mid] > arr[mid + 1]:
                right = mid
            elif arr[mid] > arr[mid - 1]:
                left = mid


def main():
    arr = [24, 69, 100, 99, 79, 78, 67, 36, 26, 19]
    # arr = [3, 4, 5, 1]
    sln = Solution()
    print(sln.peak_index_in_mountain_array(arr))  # 2


if __name__ == '__main__':
    main()

  • 执行用时: 36 ms , 在所有 Python3 提交中击败了 85.40% 的用户;
  • 内存消耗: 15.8 MB , 在所有 Python3 提交中击败了 53.48% 的用户。
  • 时间复杂度: O ( l o g n ) O(logn) O(logn),其中 n n n 是数组 arr 的长度。我们需要进行二分查找的次数为 O ( l o g n ) O(logn) O(logn)
  • 空间复杂度: O ( 1 ) O(1) O(1)

更加优雅的解法如下:

from typing import List


class Solution:
    def elegant_peak_index(self, arr: List[int]) -> int:
        left, right, idx = 1, len(arr) - 2, 0
        while left <= right:
            mid = (left + right) // 2
            if arr[mid] > arr[mid + 1]:
                idx = mid
                right = mid - 1
            else:
                left = mid + 1
        return idx


def main():
    arr = [24, 69, 100, 99, 79, 78, 67, 36, 26, 19]
    # arr = [3, 4, 5, 1]
    sln = Solution()
    print(sln.elegant_peak_index(arr))  # 2


if __name__ == '__main__':
    main()

猜你喜欢

转载自blog.csdn.net/weixin_37780776/article/details/120047871