Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Build confidence with an intuition-first walkthrough focused on array fundamentals.
Given an array of integers arr, return true if and only if it is a valid mountain array.
Recall that arr is a mountain array if and only if:
arr.length >= 3i with 0 < i < arr.length - 1 such that:
arr[0] < arr[1] < ... < arr[i - 1] < arr[i] arr[i] > arr[i + 1] > ... > arr[arr.length - 1]Example 1:
Input: arr = [2,1] Output: false
Example 2:
Input: arr = [3,5,5] Output: false
Example 3:
Input: arr = [0,3,2,1] Output: true
Constraints:
1 <= arr.length <= 1040 <= arr[i] <= 104Problem summary: Given an array of integers arr, return true if and only if it is a valid mountain array. Recall that arr is a mountain array if and only if: arr.length >= 3 There exists some i with 0 < i < arr.length - 1 such that: arr[0] < arr[1] < ... < arr[i - 1] < arr[i] arr[i] > arr[i + 1] > ... > arr[arr.length - 1]
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array
[2,1]
[3,5,5]
[0,3,2,1]
minimum-number-of-removals-to-make-mountain-array)beautiful-towers-i)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #941: Valid Mountain Array
class Solution {
public boolean validMountainArray(int[] arr) {
int n = arr.length;
if (n < 3) {
return false;
}
int i = 0, j = n - 1;
while (i + 1 < n - 1 && arr[i] < arr[i + 1]) {
++i;
}
while (j - 1 > 0 && arr[j - 1] > arr[j]) {
--j;
}
return i == j;
}
}
// Accepted solution for LeetCode #941: Valid Mountain Array
func validMountainArray(arr []int) bool {
n := len(arr)
if n < 3 {
return false
}
i, j := 0, n-1
for i+1 < n-1 && arr[i] < arr[i+1] {
i++
}
for j-1 > 0 && arr[j-1] > arr[j] {
j--
}
return i == j
}
# Accepted solution for LeetCode #941: Valid Mountain Array
class Solution:
def validMountainArray(self, arr: List[int]) -> bool:
n = len(arr)
if n < 3:
return False
i, j = 0, n - 1
while i + 1 < n - 1 and arr[i] < arr[i + 1]:
i += 1
while j - 1 > 0 and arr[j - 1] > arr[j]:
j -= 1
return i == j
// Accepted solution for LeetCode #941: Valid Mountain Array
struct Solution;
impl Solution {
fn valid_mountain_array(a: Vec<i32>) -> bool {
let n = a.len();
if n < 3 {
return false;
}
let mut i = 0;
while i + 1 < n && a[i] < a[i + 1] {
i += 1;
}
if i == 0 || i == n - 1 {
return false;
}
while i + 1 < n && a[i] > a[i + 1] {
i += 1;
}
i == n - 1
}
}
#[test]
fn test() {
let a = vec![2, 1];
assert_eq!(Solution::valid_mountain_array(a), false);
let a = vec![3, 5, 5];
assert_eq!(Solution::valid_mountain_array(a), false);
let a = vec![0, 3, 2, 1];
assert_eq!(Solution::valid_mountain_array(a), true);
}
// Accepted solution for LeetCode #941: Valid Mountain Array
function validMountainArray(arr: number[]): boolean {
const n = arr.length;
if (n < 3) {
return false;
}
let [i, j] = [0, n - 1];
while (i + 1 < n - 1 && arr[i] < arr[i + 1]) {
i++;
}
while (j - 1 > 0 && arr[j] < arr[j - 1]) {
j--;
}
return i === j;
}
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.