1、题目描述
给定一个长度为 n
的整数 山脉 数组 arr
,其中的值递增到一个 峰值元素 然后递减。
返回峰值元素的下标。
你必须设计并实现时间复杂度为 O(log(n))
的解决方案。
2、算法思路
方法一、暴力法
遍历数组,当遍历到的这个数一直和上一个数比较,如果arr[i]>arr[i-1] 就一直遍历下去,找到一个arr[i-1]> arr[i] 的数,然后返回 i-1
方法二、二分法
根据题目可以知道[left,mid]是递增,[mid,right]是递减,注意是不存在连续2个相等的数
(1)、判断条件
if (arr[mid] > arr[mid-1]) left=mid;
else if(arr[mid] < arr[mid-1])right = mid -1;
(2)、循环条件
while(left < right)不能<=,因为会进入死循环。当left-right = 1时,left=mid,还是if (arr[mid] > arr[mid-1]) left=mid;这个条件成立 就会不断的进入死循环,所以不能加=。
(3)取中点
mid = (left+right ) >>>1;和 mid = (left+right +1) >>>1;
(1)比如left=2,right=3,mid=2,如果是mid = (left+right ) >>>1时,mid=2,此时还是if (arr[mid] > arr[mid-1]) left=mid;条件成立,此时left=2,right=3,mid=2,while(left < right)成立进入死循环
(2)比如left=2,right=3,mid=2,如果是mid = (left+right +1) >>>1时,mid=3,此时还是if (arr[mid] > arr[mid-1]) left=mid;条件成立,此时left=3,right=3,mid=3,while(left < right)不成立,结束循环
3、算法代码
class Solution {
public static int peakIndexInMountainArray(int[] arr) {
//[0,mid]是递增,[mid,right]是递减,所以就返回mid
int left = 0,right = arr.length-1;
while (left < right){
int mid = (left + right +1) >>>1;
if (arr[mid] > arr[mid-1]) left=mid;
else if(arr[mid] < arr[mid-1])right = mid -1;
}
return left;
}
}