峰值索引是严格大于左右邻值的元素下标;std::max_element不能直接替代,因其仅返回全局最大值、时间复杂度o(n),且不适用于多峰值或非山形数组。

什么是峰值索引,std::max_element 能直接用吗
峰值索引指的是数组中严格大于左右邻值的元素下标(边界元素除外)。它不等价于“最大值索引”——比如 [1,3,2] 的峰值索引是 1,但 [1,2,3,4,5,4,3] 有且仅有一个峰值索引 4(值为 5),此时它恰好也是全局最大值;而 [1,3,2,4] 有两个局部峰值(3 和 4),但题目通常要求的是「满足山形数组定义」的唯一峰值,即先严格递增、后严格递减,中间只有一个峰。
std::max_element 返回的是全局最大值迭代器,它在山形数组中确实能给出峰值索引,但前提是:数组必须满足山形结构(否则结果无意义);且它时间复杂度是 O(n),没利用单调性。如果数组很大,更优解是二分查找。
用二分查找找峰值索引,关键比较逻辑是什么
山形数组中,任意位置 i 的邻居关系能提示搜索方向:
若 arr[i] ,说明还在上升段,峰值一定在右半边(含 <code>i+1);
若 arr[i] > arr[i+1],说明已过峰顶或正处下降段,峰值在左半边(含 i)。
注意边界处理:
• 不需要检查 i == 0 或 i == n-1,因为题设保证存在峰值且长度 ≥ 3;
• 比较时用 arr[mid] 和 arr[mid + 1] 最稳妥,避免访问 arr[mid - 1] 时越界;
• 使用闭区间 [left, right] 更直观,循环条件为 left ,每次收缩后必保留至少一个候选。
示例代码片段:
int peakIndexInMountainArray(vector<int>& arr) {
int left = 1, right = arr.size() - 2; // 排除两端,它们不可能是峰值
while (left <h3>为什么不能用 <code>arr[mid-1] 做判断</code>
</h3>
<p>看似等价,但实际引入两个隐患:<br>• 当 <code>mid == 0</code> 时,<code>arr[mid-1]</code> 访问越界(即使你把 <code>left</code> 设为 <code>1</code>,二分过程中仍可能算出 <code>mid = 0</code>,尤其用 <code>left = 0</code> 初始化时);<br>• 逻辑上,比较 <code>mid</code> 和 <code>mid+1</code> 直接对应“上升/下降趋势”,方向明确;而用 <code>mid-1</code> 和 <code>mid</code> 需额外考虑 <code>mid</code> 是否为首个元素,分支变多,容易写错收缩条件。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill4025" title="C++ 算法竞赛自动化测试数据生成与校验框架"><img
src="https://img.php.cn/upload/skill/000/000/081/178988956499722.jpg" alt="C++ 算法竞赛自动化测试数据生成与校验框架" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill4025" title="C++ 算法竞赛自动化测试数据生成与校验框架" class="overflowclass">C++ 算法竞赛自动化测试数据生成与校验框架</a>
<p class="overflowclass">根据原题生成新题面、验证器及完整测试数据,自动套用 testlib 模板,用于用户要求生成测试数据时。</p>
</div>
<a rel="nofollow" href="/xiazai/skill4025" title="C++ 算法竞赛自动化测试数据生成与校验框架" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<p>常见错误写法:</p>
<pre class="brush:php;toolbar:false;">// ❌ 危险:mid 可能为 0,且收缩逻辑易反
if (arr[mid-1] <h3>LeetCode 第 852 题的输入约束和测试陷阱</h3><p>该题明确约定:<br>• <code>arr.length >= 3</code>;<br>• 存在唯一峰值;<br>• <code>arr[0] 且 <code>arr[i] > arr[i+1] > ... > arr[arr.length-1]</code>。</code></p><p>这意味着你可以安全地:<br>• 跳过对边界是否为峰值的检查;<br>• 不做重复值判断(所有相邻元素不等);<br>• 不验证输入是否真为山形(OJ 保证)。</p><p>但本地调试时,如果误传 <code>[1,2,3,4,5]</code>(纯升序),你的二分会返回 <code>4</code>(末尾),而它不是峰值(无右邻可比)——这说明:算法依赖题设,脱离约束就失效。实际工程中,建议加断言或预检,例如:</p><pre class="brush:php;toolbar:false;">assert(arr.size() >= 3);
assert(arr[0] <p>峰值索引本身不难,难的是意识到:它本质是利用一维数组的“梯度方向”做二分,而不是在找最大值。一旦把问题映射成“找导数由正变负的位置”,思路就稳了。</p>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










