「这是我参与11月更文挑战的第 5 天,活动详情查看:2021最后一次更文挑战」
原题链接
852. 山脉数组的峰顶索引 - 力扣(LeetCode) (leetcode-cn.com)
题目描述
符合下列属性的数组 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.length <= 1040 <= arr[i] <= 106- 题目数据保证
arr是一个山脉数组
分析
阅读题目可得知,会有一个数组,其中必定存在一个数,以这个数对应的下标,往左则每个下标对应的数依次递减,往右则每个下标对应的数也是依次递减,也可以说,这个数组中最大的数对应的下标,就是我们期望的答案
代码
一个最简单的解法,直接从头开始遍历这个数组,一旦发现当前的数比下一个数大,则这个下标就是答案
var peakIndexInMountainArray = function(arr) {
let i=0;
for(;i<arr.length-1;i++){
if(arr[i]>arr[i+1]) return i;
}
};
这种解法最差的情况下,需要全数组遍历,他的时间复杂度为 O(n)
二分查找法
由于数组数据的特性(先一路递增,过某个点后,再一路递减),我们可以使用二分查找的的方式来将查找的速度优化为 O(log(n)),这里我们需要查找的数需要满足此条件 arr[n]>arr[n-1] && arr[n]>arr[n+1]
大致的思路为,在中间挑一个点,判断这个点是否比左右大,是则为匹配;否就比较左右两个点的大小,判断是上坡还是下坡,然后缩小边界选取中心点继续比较
var peakIndexInMountainArray = function(arr) {
let l = 0,
r = arr.length - 1;
let m;
for (; true;) {
m = Math.floor((r - l) / 2) + l
if (arr[m] > arr[m + 1] && arr[m] > arr[m - 1]) {
return m;
} else if (arr[m - 1] < arr[m + 1]) {
l = m;
} else if (arr[m - 1] > arr[m + 1]) {
r = m;
} else if (l > r) {
return -1;
}
}
};
今天的力扣刷题就分享到这里,感谢大家的阅读~