Algorithm

132 Pattern

Monotonic Stack Pattern

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.

CONSTRAINTS
  • n == nums.length
  • 1 <= n <= 2 * 10⁵
  • -10⁹ <= nums[i] <= 10⁹
EXAMPLE 1
Input: nums = [1,2,3,4]
Output: false
Strictly increasing sequence cannot satisfy the Sandwich condition (k < j).
EXAMPLE 2
Input: nums = [3,1,4,2]
Output: true
The triplet (1, 4, 2) satisfies i < k < j.
EXAMPLE 3
Input: nums = [-1,3,2,0]
Output: true
The triplet (-1, 3, 2) satisfies the 132 pattern.
Is the s2 variable strictly necessary?
Yes. s2 represents the largest possible value to the right of a larger peak. By maximizing s2, we give the current number (the potential '1') the easiest possible threshold to beat.

A 132 pattern is a sequence of three numbers—Small (1), Large (3), and Medium (2)—where the Large number sits in the middle and the Medium number is on the right. This is hard to find because it's not a simple upward or downward slope; it's a "Sandwich" where a peak is trapped between two smaller values.

A naive approach would be to check every possible triplet $(i, j, k)$, which takes O(N^3) time. We could optimize this to O(N^2) by fixing the middle "Large" number and searching for the smallest value to its left and any valid value to its right. However, to reach linear time, we need a way to track these dependencies simultaneously.

The secret to solving this in a single pass is to Search Backward. By scanning from right to left, we can resolve the relationship between the "Large" (3) and the "Medium" (2) first. We maintain a variable s2 to track the largest "Medium" candidate we've seen so far that has a larger "Large" neighbor to its left.

The strategy works as follows:
- Reverse Scan: We move through the array from right to left. Every number we see is a potential "Large" (3) candidate for the numbers to its left.
- Identify the Medium (s2): We use a monotonic stack to store potential "2" candidates. Every time the current number is larger than the top of the stack, we've found a new "Large" (3). We "pop" the stack and update s2 to be that popped value. By always taking the largest possible popped value, we give our future "Small" (1) the best chance to succeed.
- Find the Small (1): As we continue left, if we ever find a number strictly smaller than our current s2, the pattern is complete. We have our Small (1), and we know there is a Large (3) and a Medium (2) already resolved to its right.

python
# Monotonic Stack (O(N) Time, O(N) Space)
stack = []
s2 = float('-inf') # The "Medium" candidate

# Search backward to resolve 3 and 2 dependencies first
for i in range(len(nums) - 1, -1, -1):
    # If current num is "Small" enough to be less than our "Medium"
    if nums[i] < s2:
        return True
    
    # If current num is a potential "Large" (3), update "Medium" (2)
    while stack and nums[i] > stack[-1]:
        s2 = stack.pop()
    
    # Push current num as a potential candidate
    stack.append(nums[i])

return False

By using a stack in reverse, we effectively "buffer" potential candidates until we can prove they are part of a 132 sequence. Every element enters and leaves the stack at most once, ensuring linear time.

Worked Example:[3, 1, 4, 2]
0
3
1
1
2
4
3
2
i = 3 (val 2)
Scan backward. Read 2. Stack = [2]. s2 = -infinity.
0
3
1
1
2
4
i = 2 (val 4)
3
2
s2 candidate
Read 4. 4 > 2 (stack top). Pop 2, set s2 = 2. Push 4. Stack = [4], s2 = 2.
0
3
1
1
i = 1 (val 1)
2
4
3
2
Read 1. Since 1 < s2 (2), we found a 132 pattern! (nums[i] < s2 implies 1 < 2, and we know 2 is s2 because of a peak 4 to its left). Return true.
Interactive Strategy Visualization
PATTERN DETECTION ENGINE

132 Pattern Strategy

3
1
4
2
Stack (Peak)
s3 (Middle)

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".
ALGORITHMSTEP 1/5
Goal: Find i < j < k such that nums[i] < nums[k] < nums[j]. We scan from RIGHT to LEFT.
TIP

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!

O(N³) Every Triple
O(N²) Fix The Peak
O(N) Reverse Monotonic Stack