1. 题目链接:852. 山脉数组的峰顶索引
2. 题目描述:
符合下列属性的数组
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
是一个山脉数组
3. 解法2(暴力查找)
3.1 算法思路
峰顶的特点:比两侧的元素都要大
因此我们可以遍历数组中的每一个元素,找到某一个元素比两边的元素大即可
3.2 C++算法代码:
class Solution {
public:
int peakIndexInMountainArray(vector<int>& arr) {
int n=arr.size();
//遍历数组的每一个元素,直到找到峰顶元素
for(int i=1;i<n-1;i++)
{
if(arr[i]>arr[i-1]&&arr[i]>arr[i+1])
return i;
}
return -1;
}
};
4. 解法1(二分查找)
4.1 算法思路:
分析峰顶位置的数据特点,以及山峰两旁的数据的特点:
峰顶数据特点:arr[i]>arr[i-1] && arr[i]>arr[i+1]
- 峰顶左边的数据特点:
arr[i]>arr[i-1] && arr[i]<arr[i+1]
,也就是呈现向上的趋势 - 峰顶右边的数据特点:
arr[i]<arr[i-1] && arr[i]>arr[i+1]
,也就是呈现下降的趋势
根据mid
位置的信息,我们可以分为下面三种情况:
- 如果
mid
位置呈现上升趋势,说明我们接下来要在[mid+1,right]
区间继续搜索 - 如果
mid
位置呈现下降趋势,说明我们接下来要在[left,mid-1]
区间搜索 - 如果
mid
位置就是山峰,直接返回结果
4.2 C++算法代码:
class Solution {
public:
int peakIndexInMountainArray(vector<int>& arr) {
//因为第一个位置和最后一个位置决对不可能是结果
//所以左边从第二个开始,右边也从第二个开始
int left=1,right=arr.size()-2;
while(left<right)
{
int mid=left+(right-left+1)/2;
if(arr[mid]>arr[mid-1]) left=mid;
else right=mid-1;
}
return left;
}
};