山脉数组判定逻辑是:长度≥3,存在唯一峰值索引i(0<i<arr.length−1),严格先增后减,全程无相等相邻元素,且必须完成下降(即不能停在上升段);示例代码通过单次遍历维护up状态,遇升时需仍在上升段,遇降时首次标记峰过、后续须持续降,相等直接返回false,最终要求已转入下降态。

什么是山脉数组的判定逻辑
山脉数组必须满足:长度 ≥ 3,存在唯一峰值索引 i(0 i n-1),使得数组严格递增到 i,再严格递减到末尾。关键不是“看起来像山”,而是**严格单调性 + 峰值位置合法 + 无平台(相等元素)**。
常见误判点:
– 把 [1,2,2,3,4,5] 当作山脉(错在非严格递增)
– 接受 [1,3,2,1,0](对)但拒绝 [0,1,2,3,4,5,4,3,2,1,0](其实也对)
– 忘记检查长度,对 [1,2,3] 直接返回 true(错,没下降段)
用一次遍历完成判断(推荐写法)
不需要先找峰再验证两段,用状态机思想更稳:定义状态 up(正在上升)、down(已过峰,正在下降)。初始为 up,遇到下降就切到 down,之后不能再上升或持平。
实操要点:
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 开头必须严格上升,第一个下降点才允许切换状态;若首对就下降(如
[3,2,1]),直接 false - 一旦进入
down状态,后续所有arr[i] >= arr[i-1]都非法 - 全程禁止
arr[i] == arr[i-1],山脉定义要求“严格”单调 - 结束时必须处于
down状态(即确实有过下降),否则如[1,2,3,4]是 false
示例代码核心逻辑:
bool validMountainArray(vector<int>& arr) {
if (arr.size() < 3) return false;
bool up = true;
for (int i = 1; i < arr.size(); ++i) {
if (arr[i] > arr[i-1]) {
if (!up) return false; // 已经开始降了还升?
} else if (arr[i] < arr[i-1]) {
if (up) up = false; // 第一次降,标记峰已过
else if (!up && i == 1) return false; // 第一对就降,无上升段
} else {
return false; // 相等,不合法
}
}
return !up; // 必须已经转为下降态
}
为什么不用 std::is_sorted 分两段验证
有人想先用 std::max_element 找峰,再用 std::is_sorted 检查前后两段——这可行但有坑:
-
std::is_sorted(arr.begin(), it, less<int>{})默认是“非递减”,得显式传less<int>{}才保证严格递增,否则[1,2,2,3]会误判通过 - 找不到唯一峰时(如多个相同最大值),
max_element只返回第一个,后续验证必然失败,但错误原因难定位 - 时间复杂度看似 O(n),实际三次遍历(找峰 + 前段验 + 后段验),不如单次遍历清晰
- 边界处理繁琐:要确保峰不在首尾,且前后段长度都 ≥ 1
测试时容易忽略的边界 case
光测 [0,3,2,1] 不够,这些才是真卡点:
-
[1,2,3,4,5,6,7,8,9](纯升,false) -
[9,8,7,6,5,4,3,2,1](纯降,false) -
[1,2,3,3,4,5](上升中平台,false) -
[1,2,3,4,5,4,4,3,2,1](下降中平台,false) -
[1,3,2](最小合法,true) -
[3,5,5](首对升但第二对持平,false)
峰值必须是“尖”的,任何平顶、斜坡、断崖都不算。实际写的时候,宁可多写几行状态判断,也不要依赖直觉去“看形状”。

















