LeetCode 941: Valid Mountain Array (Single Pass Peak Validation)
LeetCode 941ArrayTwo PointersToday we solve LeetCode 941 - Valid Mountain Array.
Source: https://leetcode.com/problems/valid-mountain-array/
English
Problem Summary
Given an integer array arr, determine whether it forms a mountain. A valid mountain must strictly increase to a single peak, then strictly decrease, and both sides must exist.
Key Insight
Use one pointer to walk uphill first, then walk downhill. The peak cannot be at index 0 or n-1, and we must finish exactly at the last index after descending.
Brute Force and Why We Improve
A brute-force style approach tries every index as a peak and checks both sides, which can degrade to O(n^2). A single pass with two phases gives O(n) and is simpler.
Optimal Algorithm (Step-by-Step)
1) If n < 3, return false.
2) Start i = 0, move while arr[i] < arr[i+1] (climb).
3) If i == 0 or i == n-1, return false (no left side or no right side).
4) Continue while arr[i] > arr[i+1] (descend).
5) Return whether i == n-1.
Complexity Analysis
Time: O(n).
Space: O(1).
Common Pitfalls
- Allowing equal adjacent numbers (must be strict increase/decrease).
- Accepting peak at the first or last position.
- Stopping after climb and forgetting to verify full descent to the end.
Reference Implementations (Java / Go / C++ / Python / JavaScript)
class Solution {
public boolean validMountainArray(int[] arr) {
int n = arr.length;
if (n < 3) return false;
int i = 0;
while (i + 1 < n && arr[i] < arr[i + 1]) i++;
if (i == 0 || i == n - 1) return false;
while (i + 1 < n && arr[i] > arr[i + 1]) i++;
return i == n - 1;
}
}func validMountainArray(arr []int) bool {
n := len(arr)
if n < 3 {
return false
}
i := 0
for i+1 < n && arr[i] < arr[i+1] {
i++
}
if i == 0 || i == n-1 {
return false
}
for i+1 < n && arr[i] > arr[i+1] {
i++
}
return i == n-1
}class Solution {
public:
bool validMountainArray(vector<int>& arr) {
int n = (int)arr.size();
if (n < 3) return false;
int i = 0;
while (i + 1 < n && arr[i] < arr[i + 1]) ++i;
if (i == 0 || i == n - 1) return false;
while (i + 1 < n && arr[i] > arr[i + 1]) ++i;
return i == n - 1;
}
};class Solution:
def validMountainArray(self, arr: list[int]) -> bool:
n = len(arr)
if n < 3:
return False
i = 0
while i + 1 < n and arr[i] < arr[i + 1]:
i += 1
if i == 0 or i == n - 1:
return False
while i + 1 < n and arr[i] > arr[i + 1]:
i += 1
return i == n - 1var validMountainArray = function(arr) {
const n = arr.length;
if (n < 3) return false;
let i = 0;
while (i + 1 < n && arr[i] < arr[i + 1]) i++;
if (i === 0 || i === n - 1) return false;
while (i + 1 < n && arr[i] > arr[i + 1]) i++;
return i === n - 1;
};中文
题目概述
给定整数数组 arr,判断它是否是一个有效山脉数组。有效山脉要求先严格递增到唯一峰顶,再严格递减,并且峰顶左右两侧都必须存在元素。
核心思路
使用一个指针分两阶段移动:先“上坡”,再“下坡”。峰顶不能在首位或末位,并且下坡必须一路走到数组末尾才算合法。
朴素解法与优化
朴素方法可枚举每个位置当峰顶并检查两侧,最坏会到 O(n^2)。更优是单趟两阶段扫描,时间 O(n)、空间 O(1)。
最优算法(步骤)
1)若 n < 3,直接返回 false。
2)从 i = 0 出发,满足 arr[i] < arr[i+1] 时持续上坡。
3)若此时 i == 0 或 i == n-1,返回 false(说明没有完整两侧)。
4)继续在 arr[i] > arr[i+1] 条件下下坡。
5)最后判断是否恰好到达末尾:i == n-1。
复杂度分析
时间复杂度:O(n)。
空间复杂度:O(1)。
常见陷阱
- 把相等相邻元素当作可接受(本题要求严格大小关系)。
- 允许峰顶出现在第一个或最后一个位置。
- 上坡结束后未校验是否完整下坡到末尾。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class Solution {
public boolean validMountainArray(int[] arr) {
int n = arr.length;
if (n < 3) return false;
int i = 0;
while (i + 1 < n && arr[i] < arr[i + 1]) i++;
if (i == 0 || i == n - 1) return false;
while (i + 1 < n && arr[i] > arr[i + 1]) i++;
return i == n - 1;
}
}func validMountainArray(arr []int) bool {
n := len(arr)
if n < 3 {
return false
}
i := 0
for i+1 < n && arr[i] < arr[i+1] {
i++
}
if i == 0 || i == n-1 {
return false
}
for i+1 < n && arr[i] > arr[i+1] {
i++
}
return i == n-1
}class Solution {
public:
bool validMountainArray(vector<int>& arr) {
int n = (int)arr.size();
if (n < 3) return false;
int i = 0;
while (i + 1 < n && arr[i] < arr[i + 1]) ++i;
if (i == 0 || i == n - 1) return false;
while (i + 1 < n && arr[i] > arr[i + 1]) ++i;
return i == n - 1;
}
};class Solution:
def validMountainArray(self, arr: list[int]) -> bool:
n = len(arr)
if n < 3:
return False
i = 0
while i + 1 < n and arr[i] < arr[i + 1]:
i += 1
if i == 0 or i == n - 1:
return False
while i + 1 < n and arr[i] > arr[i + 1]:
i += 1
return i == n - 1var validMountainArray = function(arr) {
const n = arr.length;
if (n < 3) return false;
let i = 0;
while (i + 1 < n && arr[i] < arr[i + 1]) i++;
if (i === 0 || i === n - 1) return false;
while (i + 1 < n && arr[i] > arr[i + 1]) i++;
return i === n - 1;
};
Comments