Title: Validate a Mountain Array
In this guide, you’ll learn how to check whether a given integer array forms a valid mountain array, a classic validation problem that interviewers like because it rewards careful boundary handling rather than clever tricks. An array counts as a mountain only when it strictly rises to a single peak and then strictly falls, with that peak never sitting at the very first or very last index.
You’ll build a two-pointer Java solution that scans the array once, walk through a full trace on a tricky input, then work through examples, common mistakes, edge cases, and the kind of follow-up questions an interviewer is likely to ask next.
Understanding the Problem
Given an integer array arr, the task is to return true if arr is a mountain array and false otherwise. An array is a mountain only when its length is at least 3 and there exists an index i with 0 < i < arr.length - 1 such that the values from arr[0] to arr[i] are strictly increasing and the values from arr[i] to arr[arr.length - 1] are strictly decreasing.
The word strictly matters here. Two equal consecutive values anywhere in the array, even on an otherwise valid slope, disqualify the array as a mountain.
Approach
The cleanest solution reuses a single index across two phases instead of scanning the array more than once or allocating any extra memory.
- If
arr.lengthis less than 3, returnfalseimmediately, since no valid mountain can exist. - Start an index
iat 0 and advance it whilearr[i] < arr[i + 1], incrementingion every strict increase. - When the ascending walk stops,
ipoints at the candidate peak. Ifi == 0ori == arr.length - 1, the peak sits at an endpoint, so returnfalse. - Continue advancing from the same
iwhilearr[i] > arr[i + 1], incrementingion every strict decrease. - If the descending walk reaches the last index, every element belonged to exactly one of the two slopes, so return
true. - If the descending walk stops before the last index, a plateau or a new ascent broke the pattern, so return
false.
Java Program
Here is a complete, compilable Java program that implements the two-pointer approach described above.
public class ValidMountainArray {
public static boolean validMountainArray(int[] arr) {
int n = arr.length;
if (n < 3) {
return false;
}
int i = 0;
// Walk up the strictly increasing slope
while (i + 1 < n && arr[i] < arr[i + 1]) {
i++;
}
// The peak cannot be the first or the last index
if (i == 0 || i == n - 1) {
return false;
}
// Walk down the strictly decreasing slope
while (i + 1 < n && arr[i] > arr[i + 1]) {
i++;
}
return i == n - 1;
}
public static void main(String[] args) {
int[] mountain = {0, 3, 2, 1};
int[] notMountain = {3, 2, 1};
System.out.println(validMountainArray(mountain));
System.out.println(validMountainArray(notMountain));
}
}Explanation of the Program
The method validMountainArray stores the array length in n and rejects any array shorter than three elements right away, since a two-element array can never contain both a strict rise and a strict fall.
The first while loop advances i only while arr[i] < arr[i + 1], which traces the ascending slope. The condition i + 1 < n guards against reading past the end of the array.
Once the ascending loop stops, i is sitting on what should be the peak. The check i == 0 || i == n - 1 rejects arrays where no true peak ever appears, which happens when the array is strictly decreasing from the start or strictly increasing all the way to the end.
The second while loop reuses the same i to trace the descending slope using arr[i] > arr[i + 1]. Because it starts exactly where the ascending loop left off, the peak itself is never counted twice.
The final line, return i == n - 1, succeeds only if the descending walk consumed every remaining index. If it stopped early, something other than a clean descent broke the pattern, so the method correctly returns false.
Step-by-Step Trace
Consider the input [0, 2, 2, 3, 1] with target output false, since the equal values at indices 1 and 2 break the strict ascending slope before a real peak forms.
| Step | Phase | Comparison | Holds? | i (after) |
|---|---|---|---|---|
| 1 | Ascending | arr[0] < arr[1] | Yes | 1 |
| 2 | Ascending | arr[1] < arr[2] | No (loop stops) | 1 |
| 3 | Peak check | i == 0 or i == n – 1 | No (valid peak position) | 1 |
| 4 | Descending | arr[1] > arr[2] | No (loop stops) | 1 |
| 5 | Final check | i == n – 1 | No, returns false | 1 |
At the end of each phase, i marks the last index where the current slope’s strict inequality still held; as soon as that inequality fails, the loop stops advancing and the next phase, or the final check, takes over.
Examples
Example 1: A Valid Mountain Array
The array [0, 3, 2, 1] rises strictly from 0 to 3 and then falls strictly to 1, with the peak at index 1, which is neither the first nor the last index.
int[] arr = {0, 3, 2, 1};
System.out.println(validMountainArray(arr));
// Output: trueExample 2: A Strictly Decreasing Array
The array [3, 2, 1] never rises, so the ascending walk never advances past index 0, and the peak check i == 0 immediately returns false.
int[] arr = {3, 2, 1};
System.out.println(validMountainArray(arr));
// Output: falseExample 3: An Array That Is Too Short
The array [1, 2] has only two elements, so the length guard at the very start of the method returns false before any comparison happens.
int[] arr = {1, 2};
System.out.println(validMountainArray(arr));
// Output: falseCommon Mistakes to Avoid
These are the mistakes that most often slip into a first attempt at this problem.
- Omitting the minimum length guard – skipping the check for
arr.length < 3lets two-element arrays like[1, 2]reach the pointer logic, where the ascending loop can walk straight to the last index and incorrectly returntrue. Add the length guard as the very first line of the method. - Using non-strict comparisons – swapping the strict
<and>operators for<=and>=makes flat plateaus such as[1, 2, 2, 1]pass as mountains even though the peak is duplicated. Keep both while-loop conditions strict. - Dropping the bounds check – removing
i + 1 < nfrom either while-loop condition throwsArrayIndexOutOfBoundsExceptionon strictly increasing or strictly decreasing arrays such as[1, 2, 3], because the loop keeps comparing past the last index. Always guard withi + 1 < nbefore touchingarr[i + 1]. - Skipping the peak boundary check – leaving out the
i == 0 || i == n - 1check lets a strictly increasing array such as[1, 2, 3, 4]reach the finalreturn i == n - 1line and incorrectly returntrue, even though it never actually descends. Reject the array as soon as the ascending walk ends at an endpoint.
Edge Cases to Test
Walk through these input shapes before calling the solution finished.
- Array length less than 3
- Strictly increasing array (no descending slope)
- Strictly decreasing array (no ascending slope)
- Flat plateau at the peak
- Flat segment on the ascending or descending slope
- Peak located at index 0
- Peak located at the last index
- All elements identical
Additional Considerations
The two-pointer scan visits each element a constant number of times as i sweeps forward across the array exactly once, so the time complexity is O(n).
No auxiliary array, recursion, or extra collection is used, only the single index variable i, so the space complexity is O(1).
Because the algorithm only ever compares adjacent elements with strict less-than and greater-than operators, there is no arithmetic that could overflow, so the logic stays correct even when the array contains Integer.MIN_VALUE or Integer.MAX_VALUE.
Interview Follow-up Questions
Once the base solution is working, expect an interviewer to push on variations like these.
- What if the array contains duplicate values anywhere, not just at the peak? – no change is needed; the same strict ascending and descending scan already rejects duplicates anywhere, since equal adjacent values fail both strict comparisons.
- What if you also need the peak’s index, not just a yes or no answer? – return the index
icaptured right after the ascending loop ends, since that index is the peak whenever the array passes validation. - What if the array arrives as a stream and you can only look at each value once, in order? – track a small phase variable (ascending, descending, or invalid) and the previous value seen, updating the phase as each new value arrives instead of indexing backward.
- What if the array is far too large to fit in memory? – the same streaming approach works directly, since the algorithm only ever needs the previous element and the current phase, which makes it naturally suited to a single forward pass over out-of-core or paginated data.
Conclusion
Validating a mountain array is a great example of how a single, carefully reused index can replace what might look like it needs multiple passes or extra data structures. The strict inequality checks and the peak boundary check are the two details that trip up most first attempts.
Try adapting the same two-pointer idea to a related problem, such as locating the peak index of a mountain array with binary search. You can learn more about array-based problems like this one in the Arrays category on dailyjavaconcept.com.



