1. 题目
题目地址(852. 山脉数组的峰顶索引 - 力扣(LeetCode))
题目描述
符合下列属性的数组 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
。
你必须设计并实现时间复杂度为 O(log(n))
的解决方案。
示例 1:
输入:arr = [0,1,0] 输出:1
示例 2:
输入:arr = [0,2,1,0] 输出:1
示例 3:
输入:arr = [0,10,5,2] 输出:1
提示:
3 <= arr.length <= 105
0 <= arr[i] <= 106
- 题目数据保证
arr
是一个山脉数组
2. 题解
2.1 二分法
思路
由于题目要求时间复杂度为O(logn), 所以采用二分法
关于二分法详情参考:二分查找
代码
- 语言支持:C++
C++ Code:
class Solution {
public:
int peakIndexInMountainArray(vector<int>& arr) {
int n = arr.size();
// 左闭右闭 [1, n - 2]
// int left = 1, right = n - 2, ans = 0; // 因为是山脉数组, 必然两头 0和 n-1 是不可能的, 要找的话往中间找[1, n-2] / [1, n - 1)
// while(left <= right){
// int mid = (left + right) / 2;
// if(arr[mid] > arr[mid+1]){
// right = mid - 1;
// } else{
// left = mid + 1;
// }
// }
// 左闭右开 [1, n - 1)
// [left, right) -> [left, mid) / [mid+1, right) , 结束[left, left)
// 这里即使[left, mid) 中的 mid是最后一个也没关系, 必然会走 left = mid新(=mid旧-1) + 1,
int left = 1, right = n - 1, ans = 0;
while(left < right){
int mid = (left + right) / 2;
if(arr[mid] > arr[mid+1]){
right = mid;
} else{
left = mid + 1;
}
}
return left;
}
};
复杂度分析
令 n 为数组长度。
- 时间复杂度:\(O(logn)\)
- 空间复杂度:\(O(1)\)