【LeetCode 852 & 162_二分查找】山脉数组的峰顶索引 & 寻找峰值元素

算法场景:二分查找在「峰值问题」中的经典应用

在学习二分查找时,很多初学者都会产生疑问:

二分查找只能用来找"某个具体值"吗?

答案是否定的。
二分查找的本质,是在"有规律的区间"中不断缩小搜索范围

本篇文章将通过两道非常经典的「峰值问题」,带你真正理解 二分查找在算法中的灵活应用

  • 算法场景:二分查找在「峰值问题」中的经典应用
  • 目录
    • 一、山脉数组的峰顶索引
      • [1.1 题目链接](#1.1 题目链接)
      • [1.2 题目描述](#1.2 题目描述)
      • [1.3 题目示例](#1.3 题目示例)
      • [1.4 算法思路](#1.4 算法思路)
        • [1️⃣ 为什么可以用二分查找?](#1️⃣ 为什么可以用二分查找?)
        • [2️⃣ 如何判断?](#2️⃣ 如何判断?)
        • [3️⃣ 边界为什么从 1 到 n-2?](#3️⃣ 边界为什么从 1 到 n-2?)
      • [1.5 核心代码(C++)](#1.5 核心代码(C++))
      • [1.6 示例测试(思路演示)](#1.6 示例测试(思路演示))
    • 二、寻找峰值元素
      • [2.1 题目链接](#2.1 题目链接)
      • [2.2 题目描述](#2.2 题目描述)
      • [2.3 题目示例](#2.3 题目示例)
      • [2.4 算法思路](#2.4 算法思路)
        • [1️⃣ 核心观察](#1️⃣ 核心观察)
      • [2.5 核心代码(C++)](#2.5 核心代码(C++))
      • [2.6 示例测试(思路演示)](#2.6 示例测试(思路演示))
    • 总结

目录

一、山脉数组的峰顶索引

1.1 题目链接

👉 LeetCode852【点击进入】


1.2 题目描述

给定一个 山脉数组 arr,满足:

  • arr.length >= 3
  • 数组先严格递增,再严格递减
  • 峰顶元素既不是第一个,也不是最后一个

请你返回峰顶元素的索引。


1.3 题目示例

复制代码
输入:arr = [0,2,4,3,1]
输出:2
解释:4 是数组中的最大值,对应索引为 2

1.4 算法思路

1️⃣ 为什么可以用二分查找?

山脉数组具备明确的单调性规律

  • 峰顶左侧:递增
  • 峰顶右侧:递减

我们不需要完整遍历数组,只需判断:

  • 当前 mid 是在上坡还是下坡
2️⃣ 如何判断?

比较:

复制代码
arr[mid] 和 arr[mid - 1]
  • arr[mid] > arr[mid - 1] 👉 在上坡,峰顶在右侧
  • arr[mid] < arr[mid - 1] 👉 在下坡,峰顶在左侧(含 mid)
3️⃣ 边界为什么从 1 到 n-2?

因为题目保证:

  • 峰顶不可能是第一个或最后一个元素
  • 避免 mid-1 越界

1.5 核心代码(C++)

cpp 复制代码
class Solution {
public:
    int peakIndexInMountainArray(vector<int>& arr) {
        int left = 1;                 // 跳过起始位置
        int right = arr.size() - 2;   // 跳过末尾位置

        while (left < right) {
            int mid = left + (right - left + 1) / 2;
            if (arr[mid] > arr[mid - 1])
                left = mid;           // 在上坡,峰顶在右侧
            else
                right = mid - 1;      // 在下坡,峰顶在左侧
        }
        return left;
    }
};

1.6 示例测试(思路演示)

[0,2,4,3,1] 为例:

  • mid = 2 → 4 > 2 👉 上坡
  • left 移到 2
  • 最终 left == right == 2,返回答案

二、寻找峰值元素

2.1 题目链接

👉 https://leetcode.cn/problems/find-peak-element/description/


2.2 题目描述

给定一个数组 nums峰值元素是指:

复制代码
nums[i] > nums[i-1] 且 nums[i] > nums[i+1]

你可以假设:

  • nums[-1] = nums[n] = -∞
  • 数组中 可能有多个峰值
  • 返回任意一个即可

2.3 题目示例

复制代码
输入:nums = [1,2,3,1]
输出:2
解释:3 是峰值元素

2.4 算法思路

1️⃣ 核心观察

比较:

复制代码
nums[mid] 和 nums[mid + 1]
  • nums[mid] > nums[mid + 1]

    👉 说明左侧存在峰值(可能是 mid)

  • nums[mid] < nums[mid + 1]

    👉 说明右侧一定存在峰值

这是因为数组两端被视作 -∞峰值一定存在


2.5 核心代码(C++)

cpp 复制代码
class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        int left = 0;
        int right = nums.size() - 1;

        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] > nums[mid + 1])
                right = mid;          // 峰值在左侧
            else
                left = mid + 1;       // 峰值在右侧
        }
        return left;
    }
};

2.6 示例测试(思路演示)

[1,2,3,1] 为例:

  • mid = 1 → 2 < 3 👉 右侧有峰值
  • left = 2
  • 最终返回索引 2

总结

在本篇文章中,我们通过 「山脉数组的峰顶索引」「寻找峰值元素」 两道经典题目,深入理解了:

  • 二分查找 不只是查找某个数

  • 而是用于 在有规律的区间中缩小答案范围

  • 关键在于:

    • 找到单调性
    • 明确比较对象
    • 正确收缩区间

✨ 坚持用 清晰易懂的图解 + 代码语言, 让每个知识点都 简单直观 !

🚀 个人主页不呆头 · CSDN

🌱 代码仓库不呆头 · Gitee

📌 专栏系列

💬 座右铭 : "不患无位,患所以立。"

相关推荐
Einsail2 小时前
天梯赛题解(3-6)
算法
山楂树の2 小时前
搜索插入位置(二分查找)
数据结构·算法
东东的脑洞2 小时前
【面试突击】MySQL 查询优化核心面试知识点
mysql·面试·职场和发展
helloyangkl2 小时前
Draco——参数说明
算法
!chen3 小时前
自适应滤波算法FPGA实现思路
算法·fpga开发
救救孩子把3 小时前
51-机器学习与大模型开发数学教程-4-13 EM算法与混合模型
人工智能·算法·机器学习
Ka1Yan3 小时前
[二叉树] - 代码随想录:二叉树的统一迭代遍历
数据结构·算法·leetcode
xu_yule3 小时前
算法基础(数论)—欧拉函数
c++·算法·欧拉函数
Brduino脑机接口技术答疑3 小时前
TDCA 算法在 SSVEP 场景中的训练必要性
人工智能·算法·机器学习·脑机接口