LeetCode刷题笔记第852题:山脉数组的峰顶索引
符合下列属性的数组 arr 称为 山脉数组 :
arr.length >= 3
存在 i(0 < 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:
输入:arr = [0,1,0]
输出:1
示例 2:
输入:arr = [0,2,1,0]
输出:1
示例 3:
输入:arr = [0,10,5,2]
输出:1
示例 4:
输入:arr = [3,4,5,1]
输出:2
示例 5:
输入:arr = [24,69,100,99,79,78,67,36,26,19]
输出:2
提示:
3 <= arr.length <= 104
0 <= arr[i] <= 106
题目数据保证 arr 是一个山脉数组
进阶:很容易想到时间复杂度 O(n) 的解决方案,你可以设计一个 O(log(n)) 的解决方案吗?
想法一:
先将数组转换为集合,找到集合中最大的值,再遍历数组找到该数值的位置。
class Solution:
def peakIndexInMountainArray(self, arr: List[int]) -> int:
# 将数组转换为集合
set_arr = set(arr)
# 找出集合中最大的数
max_num = max(set_arr)
# 遍历数组得到山脉数组的峰顶索引
for i in range(len(arr)):
if arr[i] == max_num:
return i
想法二:
循环数组,当后一个位置数值小于当前位置数值时,即得到峰值。
class Solution:
def peakIndexInMountainArray(self, arr: List[int]) -> int:
# 循环遍历数组
for i in range(len(arr)):
# 当前位置数值大于后一个位置数值时,返回当前位置
if arr[i] > arr[i+1]:
return i
想法三:
二分查找,设置两个位置变量,设置为数组的头和尾,取两个位置的一半处,判断此处数值与后一个位置数值之间的大小。如果此处数值大,说明峰值位置在此处或者此处的左侧,将此处的位置赋值给尾部变量,直至循环结束返回峰值位置。如果此处数值小,说明峰值在此处的右侧,将此处的位置赋值加一给头部变量,直至循环结束返回峰值位置。
class Solution:
def peakIndexInMountainArray(self, arr: List[int]) -> int:
lo, hi = 0, len(arr) - 1
while lo < hi:
mi = (lo + hi) // 2
if arr[mi] < arr[mi + 1]:
lo = mi + 1
else:
hi = mi
return lo