力扣852. 山脉数组的峰顶索引题解

前言

大家好!今天我们来聊聊力扣(LeetCode)上的一道经典题目——山脉数组的峰顶索引。这道题目不仅能帮助我们巩固二分查找的知识,还能提高我们解决复杂问题的能力。话不多说,我们直接进入正题!

题目描述

给定一个长度为 n n n 的整数山脉数组 arr,其中的值递增到一个峰值元素后再递减。我们需要返回峰值元素的下标。

示例

  1. 示例 1

    • 输入:arr = [0,1,0]
    • 输出:1
  2. 示例 2

    • 输入:arr = [0,2,1,0]
    • 输出:1
  3. 示例 3

    • 输入:arr = [0,10,5,2]
    • 输出:1

提示

  • 数组长度 3 ≤ a r r . l e n g t h ≤ 1 0 5 3 \leq arr.length \leq 10^5 3arr.length105
  • 数组元素范围 0 ≤ a r r [ i ] ≤ 1 0 6 0 \leq arr[i] \leq 10^6 0arr[i]106
  • 题目数据保证 arr 是一个山脉数组

解题思路

看到这个题目,我们首先想到的是通过遍历数组来找到峰值元素的下标。然而,这样的做法时间复杂度是 O ( n ) O(n) O(n),并不符合题目要求的 O ( log ⁡ ( n ) ) O(\log(n)) O(log(n))。因此,我们需要使用更高效的方法——二分查找。

二分查找的思路

二分查找的核心思想是通过不断缩小搜索区间来找到目标值。在这道题目中,我们可以通过比较中间元素与其相邻元素的大小来判断峰值的方向。

具体步骤如下:

  1. 初始化左右指针 leftright,分别指向数组的起始和末尾。
  2. 计算中间位置 mid
  3. 比较 arr[mid]arr[mid + 1]
    • 如果 arr[mid] > arr[mid + 1],说明峰值在左侧(包括 mid),将 right 更新为 mid
    • 否则,说明峰值在右侧,将 left 更新为 mid + 1
  4. 重复上述步骤,直到 leftright 重合,此时的索引即为峰值元素的下标。

代码实现

理解了思路后,我们可以很容易地将其转化为代码。以下是 Java 实现:

class Solution {
    public int peakIndexInMountainArray(int[] arr) {
        int left = 0;
        int right = arr.length - 1;
        while (left < right) {
            int mid = (left + right) / 2;
            if (arr[mid] > arr[mid + 1] || mid == right) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }
}

代码解释

  • 初始化 left 为 0,right 为数组长度减 1。
  • 进入 while 循环,只要 left 小于 right 就继续。
  • 计算 midleftright 的中间位置。
  • 判断 arr[mid]arr[mid + 1] 的大小:
    • 如果 arr[mid] > arr[mid + 1],更新 rightmid,表示峰值在左侧。
    • 否则,更新 leftmid + 1,表示峰值在右侧。
  • 最后返回 left,即峰值元素的下标。

总结

这道题目通过山脉数组的特性,让我们更好地理解了二分查找的应用场景。希望大家通过这篇博客,能够掌握在类似问题中如何使用二分查找提高效率。祝大家刷题愉快!


  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值