【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

📌 专栏系列

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

相关推荐
灵感__idea13 小时前
Hello 算法:众里寻她千“百度”
前端·javascript·算法
Wect1 天前
LeetCode 130. 被围绕的区域:两种解法详解(BFS/DFS)
前端·算法·typescript
NAGNIP1 天前
一文搞懂深度学习中的通用逼近定理!
人工智能·算法·面试
颜酱2 天前
单调栈:从模板到实战
javascript·后端·算法
CoovallyAIHub2 天前
仿生学突破:SILD模型如何让无人机在电力线迷宫中发现“隐形威胁”
深度学习·算法·计算机视觉
CoovallyAIHub2 天前
从春晚机器人到零样本革命:YOLO26-Pose姿态估计实战指南
深度学习·算法·计算机视觉
CoovallyAIHub2 天前
Le-DETR:省80%预训练数据,这个实时检测Transformer刷新SOTA|Georgia Tech & 北交大
深度学习·算法·计算机视觉
CoovallyAIHub2 天前
强化学习凭什么比监督学习更聪明?RL的“聪明”并非来自算法,而是因为它学会了“挑食”
深度学习·算法·计算机视觉
CoovallyAIHub2 天前
YOLO-IOD深度解析:打破实时增量目标检测的三重知识冲突
深度学习·算法·计算机视觉
NAGNIP2 天前
轻松搞懂全连接神经网络结构!
人工智能·算法·面试