132 Pattern
Given an array of n integers nums, a 132 pattern is a subsequence of three integers nums[i], nums[j] and nums[k] such that i < j < k and nums[i] < nums[k] < nums[j]. Return true if there is a 132 pattern in nums, otherwise return false.
- n == nums.length
- 1 <= n <= 2 * 10⁵
- -10⁹ <= nums[i] <= 10⁹
nums = [1,2,3,4]falsenums = [3,1,4,2]truenums = [-1,3,2,0]trueA 132 pattern is three positions i < j < k whose values make the shape low, high, medium: nums[i] < nums[k] < nums[j]. The peak (the "3") is in the middle, and just to its right sits a value that clears the left one but stays under the peak. It's slippery to detect because it's neither a clean rise nor a clean fall — it's a low point, then a spike, then a partial come-down.
Checking all triples is O(N³). Fixing the middle peak and searching both sides drops it to O(N²). To reach a single linear pass, the trick is to scan from the right and nail down the "3" and the "2" before looking for the "1".
Carry two things as you move leftward: a stack of numbers that could still act as the peak, and a value s2 — the best "medium" locked in so far, meaning the largest number you've seen that you know has a strictly taller number to its left. Start s2 at negative infinity (nothing locked yet). For each number:
- Could it be the "1"? If it's strictly less than s2, you're done — there's already a peak-and-medium pair to its right with peak > s2 > this. Return true.
- Could it be a taller peak? While it's bigger than the top of the stack, pop; each popped value now has this bigger number to its left, so it qualifies as a "medium" — raise s2 to the largest value you pop. (Taking the largest sets the easiest bar for a future "1" to slip under.)
- Push it as a fresh peak candidate.
Why hold a stack instead of a single value? A number that's smaller than something already scanned to its right might still become the "2" for an even taller peak further left, so you can't discard it — you park it. The stack keeps these candidates in order and, because each number is pushed and popped at most once, the whole reverse scan stays linear. This is the monotonic stack again, just run right-to-left and paired with the running s2.
# Reverse monotonic stack (O(N) Time, O(N) Space)
stack = []
s2 = float('-inf') # best "medium" with a taller peak to its left
for i in range(len(nums) - 1, -1, -1):
if nums[i] < s2: # nums[i] is the "1" — pattern complete
return True
while stack and nums[i] > stack[-1]:
s2 = stack.pop() # nums[i] is a taller peak; popped value is a "medium"
stack.append(nums[i])
return False2 (rightmost) → not below s2(-∞); stack empty; push. Stack: [2]4 → not below s2; 4 > 2, pop 2 and set s2 = 2; push 4. Stack: [4], s2 = 21 → 1 < s2(2) → return true (the triple is 1 < 2 < 4).132 Pattern Strategy
1-3-2 logic
- R to L Scan: Find the 'Peak' and 'Middle' before reaching the 'Start'.
- The Stack: Maintains candidates for the peak "3".
Peak-Valley-Peak
By preserving the largest popped value as s3, we satisfy 1 < 2 < 3. If any element to the left of our peak is smaller than s3, we've found it!