Python 0845.py
class Solution:
def longestMountain(self, arr: List[int]) -> int:
result = 0
for i in range(1, len(arr) - 1):
if arr[i-1] >= arr[i] or arr[i] <= arr[i+1]:
continue
left = i - 1
right = i + 1
while left > 0 and arr[left - 1] < arr[left]:
left -= 1
while right < len(arr) - 1 and arr[right] > arr[right + 1]:
right += 1
result = max(result, right - left + 1)
return result
Difficulty
and has an acceptance rate of about 42% (400k+ submissions).
Typical patterns to solve this problem:
- Array
- Dynamic Programming
- Enumeration
- Two Pointers
AI Disclaimer
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.
See this dedicated page for more details.
Code Walkthrough
Overview
The implementation computes the length of the longest “mountain” in an integer array. A mountain is defined as a sub-array that strictly increases to a single peak and then strictly decreases, with a minimum length of three. The algorithm iterates through the array, treats each element that could be a peak, expands outward to determine the full extent of the mountain, and keeps track of the maximum length found.
Key Steps
Detecting a Potential Peak
The loop starts at the second element and stops before the last element, because a peak cannot be at the boundaries. For each index i the code checks whether the element is higher than both its immediate neighbours. If either neighbour is not lower, the iteration skips further processing.
for i in range(1, len(arr) - 1):
if arr[i-1] >= arr[i] or arr[i] <= arr[i+1]:
continue
This early-exit condition eliminates positions that cannot serve as the apex of a mountain, reducing unnecessary work.
Expanding to the Left
When a valid peak is found, the algorithm moves leftward while the sequence remains strictly increasing. The left pointer stops either at the first element or when the monotonic increase breaks.
left = i - 1
while left > 0 and arr[left - 1] < arr[left]:
left -= 1
The condition left > 0 prevents out-of-range access, and the strict < comparison guarantees that flat or decreasing sections are not included in the left slope.
Expanding to the Right
Similarly, the right pointer moves rightward while the sequence is strictly decreasing. The loop stops at the array’s end or when the decreasing pattern ends.
right = i + 1
while right < len(arr) - 1 and arr[right] > arr[right + 1]:
right += 1
The right < len(arr) - 1 guard protects against index overflow, and the > comparison enforces a proper descending slope.
Updating the Result
After both sides are expanded, the length of the current mountain is right - left + 1. The algorithm updates the global maximum if this length exceeds the previous best.
result = max(result, right - left + 1)
Finally, after all candidates have been examined, the function returns the longest length found, or 0 if no mountain exists.
return result
Edge Cases Handled
The code gracefully handles arrays that are too short to contain a mountain because the outer loop’s range becomes empty, leaving result at its initial value of 0. Flat regions where consecutive elements are equal are excluded by the strict inequality checks in both the peak detection and the expansion loops. Peaks located near the boundaries are automatically ignored because the loop does not consider the first or last index as a possible peak, ensuring that a valid mountain always has elements on both sides of the peak.
When multiple mountains are present, each potential peak is examined independently, and the longest one is retained through the max operation. The left-expansion loop stops at the first element that fails the increasing condition, preventing the algorithm from mistakenly merging adjacent mountains.
Performance Optimizations
The algorithm avoids a full scan of every possible sub-array by focusing only on indices that satisfy the peak condition. The early continue eliminates the majority of positions in arrays with many flat or monotonic sections. The left and right expansions are performed only once per valid peak, and each expansion moves the pointers strictly outward, never revisiting elements already examined for a different peak. This localized scanning reduces the total number of element accesses compared to a naïve double-nested approach.
By keeping the result in a single integer variable and updating it in place, the implementation minimizes memory overhead. The use of simple while loops with direct index arithmetic ensures that the core operations remain lightweight and cache-friendly.
ELI5 - Simplified Explanation
Imagine walking along a bumpy path made of numbers. To find the biggest mountain, look for a spot where the ground goes up and then down right after. The code starts by walking through the line of numbers and looks for a peak point. A peak is a number that is taller than the neighbor on the left and taller than the neighbor on the right.
When a peak is found, the path starts looking backward to see how far down the hill goes on the left side, and then it looks forward to see how far down the hill goes on the right side. These two directions define the start and the end of the mountain. After measuring the distance between the start and the end, the code checks to see if this mountain is bigger than the biggest one found so far, and it keeps the larger size. This keeps happening until the end of the path is reached.
Code Quality
Complexity Analysis
Other Solutions
Obviously, I did that after I solved the problem myself.
In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.
And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.
(click on a column header to sort the table)
| author | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| author | solutions | |||||||||
| www | AlgoMonster | C++ | Python | Java | TS | |||||
| WalkCCC | C++ | Python | Java | |||||||
| leetcode.ca | C++ | Python | Java | Go | TS | |||||
| LeetcodeHelp | C++ | Python | Java | |||||||
| Progiez | C++ | Python | Java | |||||||
| github | black-shadows | C++ | ||||||||
| charles-wangkai | Java | |||||||||
| DimitrisJim | C | |||||||||
| everthis | JS | |||||||||
| fengvyi | C++ | |||||||||
| fsq | C++ | |||||||||
| halfrost | Go | |||||||||
| JoshCrozier | JS | |||||||||
| lkwq007 | Python | |||||||||
| ruoru | Rust | |||||||||
| suxrobGM | C# | |||||||||
| trung-hn | Python | |||||||||
| YuriSpiridonov | Python | |||||||||
| zfang399 | C++ | |||||||||
| AlgoMonster | C++, Python, Java, TypeScript | |||||||||
| WalkCCC | C++, Python, Java | |||||||||
| leetcode.ca | C++, Go, Java, Python, TypeScript | |||||||||
| LeetcodeHelp | C++, Java, Python | |||||||||
| Progiez | C++, Java, Python | |||||||||
| black-shadows | C++, C++ | |||||||||
| charles-wangkai | Java | |||||||||
| DimitrisJim | C | |||||||||
| everthis | JavaScript | |||||||||
| fengvyi | C++ | |||||||||
| fsq | C++ | |||||||||
| halfrost | Go | |||||||||
| JoshCrozier | JavaScript | |||||||||
| lkwq007 | Python | |||||||||
| ruoru | Rust | |||||||||
| suxrobGM | C# | |||||||||
| trung-hn | Python | |||||||||
| YuriSpiridonov | Python | |||||||||
| zfang399 | C++ |
Videos
Solved On The Same Day
- problem 869: Reordered Power of 2
- problem 958: Check Completeness of a Binary Tree
- problem 988: Smallest String Starting From Leaf
- problem 1291: Sequential Digits
- problem 753: Cracking the Safe
- problem 829: Consecutive Numbers Sum
- problem 1515: Best Position for a Service Centre
Extra
- Tech Stack - my development environment and tools
- AI - how AI helped me create this website (NOT solving the problems)
- Progress - progression over time
- Quality - code quality