Advertisement
Home Data Structure Arrays Validate a Mountain Array

Validate a Mountain Array

1
Advertisement

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.

  1. If arr.length is less than 3, return false immediately, since no valid mountain can exist.
  2. Start an index i at 0 and advance it while arr[i] < arr[i + 1], incrementing i on every strict increase.
  3. When the ascending walk stops, i points at the candidate peak. If i == 0 or i == arr.length - 1, the peak sits at an endpoint, so return false.
  4. Continue advancing from the same i while arr[i] > arr[i + 1], incrementing i on every strict decrease.
  5. If the descending walk reaches the last index, every element belonged to exactly one of the two slopes, so return true.
  6. 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.

Java
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.

StepPhaseComparisonHolds?i (after)
1Ascendingarr[0] < arr[1]Yes1
2Ascendingarr[1] < arr[2]No (loop stops)1
3Peak checki == 0 or i == n – 1No (valid peak position)1
4Descendingarr[1] > arr[2]No (loop stops)1
5Final checki == n – 1No, returns false1

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.

Java
int[] arr = {0, 3, 2, 1};
System.out.println(validMountainArray(arr));
// Output: true

Example 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.

Java
int[] arr = {3, 2, 1};
System.out.println(validMountainArray(arr));
// Output: false

Example 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.

Java
int[] arr = {1, 2};
System.out.println(validMountainArray(arr));
// Output: false

Common 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 < 3 lets two-element arrays like [1, 2] reach the pointer logic, where the ascending loop can walk straight to the last index and incorrectly return true. 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 < n from either while-loop condition throws ArrayIndexOutOfBoundsException on strictly increasing or strictly decreasing arrays such as [1, 2, 3], because the loop keeps comparing past the last index. Always guard with i + 1 < n before touching arr[i + 1].
  • Skipping the peak boundary check – leaving out the i == 0 || i == n - 1 check lets a strictly increasing array such as [1, 2, 3, 4] reach the final return i == n - 1 line and incorrectly return true, 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 i captured 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.