Title: Find Maximum Length of a Mountain Subarray
In this guide, you’ll learn how to find the maximum length of a mountain subarray inside an integer array using Java. A mountain subarray is a contiguous run of elements that strictly increases to a single peak and then strictly decreases, and it must contain at least three elements. We’ll build an efficient two-pointer solution, trace it step by step on a sample input, and cover the common mistakes, edge cases, and interview follow-up questions that come up when this problem appears in a technical interview.
Understanding the Problem
Given an array of integers arr, a subarray arr[left..right] is called a mountain if it satisfies two conditions. First, there is some peak index p with left < p < right such that the values strictly increase from left to p. Second, the values strictly decrease from p to right. Because a mountain needs at least one step up and one step down, its minimum possible length is 3.
The task is to return the length of the longest such subarray anywhere in arr. If no mountain exists at all, for example when the array is flat, strictly increasing, or strictly decreasing from end to end, the answer is 0. The peak itself can never be at index 0 or at the last index, since a peak needs a strictly smaller neighbor on both sides.
Approach to Solve the Problem
The efficient way to solve this is a single forward pass that expands outward from every peak it finds, skipping any index it has already classified. Here’s the step-by-step approach:
- If the array has fewer than 3 elements, return 0 immediately since no mountain can fit.
- Start a pointer
iat index 1, since a peak can never sit at index 0 or at the last index. - At each
i, test whether it is a true peak:arr[i-1] < arr[i]andarr[i] > arr[i+1]. - If
arr[i]is a peak, walk aleftpointer backward fromiwhile the array keeps strictly increasing. - Walk a
rightpointer forward fromiwhile the array keeps strictly decreasing. - Compute the mountain length as
right - left + 1and updatemaxLengthif this mountain is longer than any seen so far. - Move
itoright + 1so the descending slope you just measured is never rescanned as if it were a new ascent. - If
arr[i]is not a peak, simply incrementiand keep scanning. Repeat untilireachesn - 1, then returnmaxLength.
Java Program
Here is the complete, compilable Java program implementing the two-pointer approach described above:
public class LongestMountainSubarray {
public static int longestMountain(int[] arr) {
int n = arr.length;
if (n < 3) {
return 0;
}
int maxLength = 0;
int i = 1;
while (i < n - 1) {
boolean isPeak = arr[i - 1] < arr[i] && arr[i] > arr[i + 1];
if (isPeak) {
int left = i;
int right = i;
while (left > 0 && arr[left - 1] < arr[left]) {
left--;
}
while (right < n - 1 && arr[right] > arr[right + 1]) {
right++;
}
int length = right - left + 1;
maxLength = Math.max(maxLength, length);
i = right + 1;
} else {
i++;
}
}
return maxLength;
}
public static void main(String[] args) {
int[] arr = {2, 1, 4, 7, 3, 2, 5};
int result = longestMountain(arr);
System.out.println("Longest mountain length: " + result);
}
}Explanation of the Program
longestMountainfirst guards against arrays shorter than 3 elements, since those can never contain a mountain.- The outer
while (i < n - 1)loop scans every candidate peak position exactly once, never revisiting an index that was already part of a measured mountain. isPeakchecks both slopes aroundarr[i]using strict comparisons, which is what rules out flat plateaus from counting as part of a mountain.- When a peak is found, the first inner
whileloop extendsleftbackward as far as the ascent continues, and the second extendsrightforward as far as the descent continues. Math.max(maxLength, length)keeps the best mountain seen across the whole array, not just the most recently measured one.- Setting
i = right + 1after measuring a mountain is the key optimization. It guarantees every element is visited only a constant number of times, keeping the whole algorithm O(n).
Step-by-Step Trace
Let's trace longestMountain on the input [0, 2, 5, 3, 1, 1, 4], which contains one clear mountain followed by a plateau, so the target output is 5.
| i | arr[i-1] < arr[i]? | arr[i] > arr[i+1]? | Is Peak? | Mountain Length | maxLength (after) |
|---|---|---|---|---|---|
| 1 | Yes | No | No | - | 0 |
| 2 | Yes | Yes | Yes (left expands to 0, right expands to 4) | 5 | 5 |
| 5 | No | - | No | - | 5 |
At the end of each iteration, maxLength holds the length of the longest mountain discovered among all peaks examined so far, and i always points just past the last index already classified, so no element is ever rescanned.
Examples
Example 1: No Mountain Exists
A completely flat array has no strict ascent or descent anywhere, so the answer is 0.
int[] arr1 = {5, 5, 5, 5};
System.out.println(longestMountain(arr1));
// Output: 0 (every pair of neighbors is equal, so no peak qualifies)Example 2: The Smallest Possible Mountain
A mountain only needs one ascending step and one descending step, so a three-element array can itself be the whole mountain.
int[] arr2 = {1, 3, 2};
System.out.println(longestMountain(arr2));
// Output: 3 (the entire array is itself a mountain)Example 3: Multiple Mountains, Longest Wins
When an array contains more than one mountain, longestMountain must keep scanning past the first one and report the overall maximum.
int[] arr3 = {2, 1, 4, 7, 3, 2, 5, 6, 8, 4, 1};
System.out.println(longestMountain(arr3));
// Output: 6 (the second mountain, [2, 5, 6, 8, 4, 1], is longer than the first, [1, 4, 7, 3, 2])Common Mistakes to Avoid
These are the mistakes that most often slip into a first attempt at this problem:
- Using >= or <= instead of strict > and <. Treating equal neighbors as part of a slope lets flat plateaus count toward a mountain, which inflates the result on inputs like
[1, 2, 2, 1]. Always require strictly increasing and strictly decreasing comparisons. - Missing boundary guards on the expansion loops. Expanding
leftbelow index 0 orrightaboven - 1throwsArrayIndexOutOfBoundsException. Guard both inner loops withleft > 0andright < n - 1. - Declaring left and right outside the peak check. Reusing stale values from a previous mountain's expansion corrupts the length calculation for the next one. Declare
leftandrightfresh inside theifblock, both starting ati. - Forgetting to jump i to right + 1. Leaving
iwhere it was and incrementing by one just rescans the descending slope you already measured, which doesn't break correctness but turns the linear algorithm back into a slower one. - Returning as soon as the first mountain is found. Some early attempts return the mountain length the moment a peak is detected instead of continuing the scan. Always track a running
maxLengthand only return it after the loop finishes.
Edge Cases to Test
Before calling this solved, make sure it behaves correctly on these inputs:
- Array with fewer than 3 elements
- Strictly increasing array (no descent)
- Strictly decreasing array (no ascent)
- All elements equal
- Plateau between two slopes (equal adjacent values)
- Multiple mountains of different lengths
- Peak adjacent to the array boundary
- Very large array (confirming O(n) performance holds)
Additional Considerations
Time complexity: O(n). Although the expansion loops for left and right look like nested iteration, jumping i to right + 1 guarantees every index is visited only a constant number of times across the entire run, so the total work stays linear in the size of arr.
Space complexity: O(1) extra space. The solution only tracks a handful of index variables, i, left, right, and maxLength, and never allocates an auxiliary array.
Compared to a brute-force approach that checks every possible subarray and verifies its shape, which costs O(n^2) time or worse, the two-pointer scan is the standard efficient solution interviewers expect. It also never mutates the input array, so it's safe to use on read-only data.
Interview Follow-up Questions
An interviewer rarely stops at the base problem. Here are the natural follow-ups, from easiest to hardest:
- What if you only need to know whether any mountain exists, not its length? Return true the moment the first peak is confirmed on both sides, short-circuiting before scanning the rest of the array.
- What if the array is read-only and you cannot allocate even a temporary array? The two-pointer approach already satisfies this, since it only uses scalar index variables. Point out that it meets the constraint by design.
- What if you need the actual start and end indices of the longest mountain, not just its length? Track
bestLeftandbestRightalongsidemaxLength, and update all three together whenever a strictly longer mountain is found. - What if duplicate adjacent values should still count toward the slope? Relaxing the comparisons to
<=and>=changes the problem definition, since a fully flat array would then register as a trivial mountain, so you would need an extra tie-breaking check to keep plateaus from being misclassified as peaks. - What if the array arrives as a stream of unknown length instead of a fixed array? Maintain a small state machine over the last few elements (ascending, descending, or flat) plus the best mountain length seen so far, since you can no longer index backward once elements have scrolled out of view.
Conclusion
Finding the maximum length of a mountain subarray comes down to recognizing that every element belongs to at most one mountain, which is exactly what lets the two-pointer expand-and-skip technique run in a single O(n) pass. Once you're comfortable with longestMountain, try adapting it to return the mountain's indices or to work over a streamed input, both of which are common interview extensions.
You can find more array-based problems like this one, with the same step-by-step trace and interview-style breakdown, in the Arrays category on DailyJavaConcept.



