二分查找习题篇(下)
1.山脉数组的峰顶索引
题目描述:
给定一个长度为
n
的整数 山脉 数组arr
,其中的值递增到一个 峰值元素 然后递减。返回峰值元素的下标。
你必须设计并实现时间复杂度为
O(log(n))
的解决方案。示例 1:
输入:arr = [0,1,0] 输出:1
示例 2:
输入:arr = [0,2,1,0] 输出:1
示例 3:
输入:arr = [0,10,5,2] 输出:1
解法一:暴力枚举 O(N)
算法思路:
根据峰顶值的特点(比两侧元素都要大),遍历数组内的每一个元素,找到一个比左右两边元素都大的元素即可。
代码实现:
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;
// 为了处理 oj 需要控制所有路径都有返回值
return -1;
}
};
解法二:二分查找算法
算法思路:
由题意我们可以将数组分为两部分,以峰顶值元素
i
为界,i
左边区域是arr[i]>arr[i-1]
,i
右边区域是arr[i]<arr[i-1]
。即具有“二段性”,可以用二分查找。
算法流程:
1.令
left=0,right=arr.size()-1;
2.当
left<right
时,下列一直循环:找到待查找区间的中间点
mid
,找到之后分两种情况讨论:
- 当
arr[mid]>arr[mid-1]
,说明mid
处于i的左边区域,更新left=mid
;- 当
arr[mid]<arr[mid-1]
,说明mid
处于i的右边区域,更新