Problem
An array forms a valid mountain if it strictly increases up to some peak element, then strictly decreases after it. The peak cannot be the first or last element โ the array must both climb to it and descend from it.
Given an integer array, determine whether it forms a valid mountain.
- Input:
arr = [0, 3, 2, 1] - Output:
true - Explanation: The array climbs from 0 to the peak at 3, then descends to 1.
Counter-examples: [0, 1, 2, 3] (only rises, never falls โ false), [3, 2, 1, 0] (only falls, never rises โ false), [0, 3, 3, 2] (equal elements at the top violate strict increase โ false).
Intuition
The core question is: does the array go up, then come down, with no flat spots? Walk from the left until you stop ascending โ that's the candidate peak. If the peak is at the very start or very end, there's no room for both sides of the mountain, so it fails immediately. Then walk down from the peak; if you reach the last element exactly, the mountain is valid.
Solution โ Walk Up Then Down
Scan from left to right in two phases: first, advance while elements are strictly increasing to find the peak; second, advance while elements are strictly decreasing. If both phases together consume the entire array โ and the peak is not at a boundary โ it's a valid mountain.
- Start an index pointer at 0.
- Advance the pointer while the next element is strictly greater (ascending phase).
- If the pointer sits at index 0, there was no ascent โ return false.
- If the pointer sits at the last index, there was no descent โ return false.
- Advance the pointer while the next element is strictly smaller (descending phase).
- Return true only if the pointer now sits at the last index, meaning the descent consumed the rest of the array.
1def validMountainArray(arr: list[int]) -> bool:
2 n = len(arr)
3 index = 0
4
5 # Walk up: advance while strictly increasing
6 while index + 1 < n and arr[index] < arr[index + 1]:
7 index += 1
8
9 # Peak can't be the first or last element
10 if index == 0 or index == n - 1:
11 return False
12
13 # Walk down: advance while strictly decreasing
14 while index + 1 < n and arr[index] > arr[index + 1]:
15 index += 1
16
17 # Valid only if we consumed the entire array in both phases
18 return index == n - 1Time: O(n) โ each element is visited at most once across both phases.
Space: O(1) โ only a single integer index is tracked.
Complexity Summary
| Approach | Time | Space | When to use |
|---|---|---|---|
| Walk Up Then Down | O(n) | O(1) | Always โ this is the only viable approach |
Common Mistakes
- Not checking that the peak isn't at index 0 โ a purely descending array like
[5, 4, 3]never enters the ascending loop, leavingindex = 0, so the guard catches it. - Not checking that the peak isn't at the last index โ a purely ascending array like
[1, 2, 3]runs the ascending loop to the end, leavingindex = n - 1, so the guard catches it. - Using
<=instead of<in the ascending condition โ[0, 3, 3, 2]has a flat section at the top;arr[index] <= arr[index + 1]would incorrectly advance through equal elements. - Forgetting to reach the last index after the descent โ
[0, 3, 2, 2]has a flat section on the way down; the descending loop stops at the duplicate, and the final checkindex == n - 1correctly returns false. - Relying on the maximum value to find the peak โ duplicates of the max (e.g.
[1, 3, 3, 2]) produce ambiguous results; the walk-and-check approach handles this naturally.
Related Problems
Peak Index in a Mountain Arrayโ given a guaranteed mountain array, locate the peak efficiently with binary searchFind Peak Elementโ generalization: any local peak is valid, solved with binary searchContainer with Most Waterโ two-pointer scan that advances from both ends based on a structural conditionValid Palindromeโ same single-pass structural validation pattern applied to stringsIncreasing Triplet Subsequenceโ detecting a structural pattern (three increasing elements) in a single array pass