【力扣刷题】852. 山脉数组的峰顶索引 | 二分法

175 阅读1分钟

「这是我参与11月更文挑战的第 5 天,活动详情查看:2021最后一次更文挑战

原题链接

852. 山脉数组的峰顶索引 - 力扣(LeetCode) (leetcode-cn.com)

题目描述

符合下列属性的数组 arr 称为 山脉数组 :

- arr.length >= 3
- 存在 i0 < 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 <= 104
  • 0 <= 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;
        }
    }
};

今天的力扣刷题就分享到这里,感谢大家的阅读~