456. 132 Pattern - Explanation
Description
Return true if there are indices i < j < k such that nums[i] < nums[k] < nums[j]. The three selected values do not need to be adjacent. Otherwise return false.
Example 1:
Input: nums = [1,4,2]
Output: trueExplanation: Use indices (0, 1, 2): their values satisfy 1 < 2 < 4, so they form a 132 pattern.
Example 2:
Input: nums = [4,3,2,1]
Output: falseExplanation: The array strictly decreases, so the first selected value can never be smaller than the third selected value.
Example 3:
Input: nums = [1,2,2]
Output: falseExplanation: The only triple has equal second and third values. The inequalities must be strict, so it is not a 132 pattern.
Constraints:
1 <= nums.length <= 200000-1000000000 <= nums[i] <= 1000000000
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Monotonic Stacks - The optimal solution uses a decreasing monotonic stack to efficiently track potential pattern candidates
- Array Traversal Patterns - Understanding both left-to-right and right-to-left traversal strategies
- Tracking Running Minimum/Maximum - Maintaining the minimum value seen so far while iterating through an array
1. Brute Force
Intuition
The most straightforward way to find a 132 pattern is to check every possible triplet. We need indices i < j < k where nums[i] < nums[k] < nums[j]. For each position k, we look backward to find a valid j (where nums[j] > nums[k]), and then look further back to find a valid i (where nums[i] < nums[k]). If all three conditions are met, we found the pattern.
Algorithm
- Iterate
kfrom index 2 to the end of the array. - For each
k, iteratejbackward fromk - 1to 1.- Skip if
nums[j] <= nums[k]since we neednums[j] > nums[k].
- Skip if
- For each valid
j, iterateibackward fromj - 1to 0.- If
nums[i] < nums[k], returntrue.
- If
- If no valid triplet is found, return
false.
Time & Space Complexity
- Time complexity:
- Space complexity:
2. Stack
Intuition
Instead of checking every triplet, we can use a monotonic decreasing stack to efficiently track potential j candidates along with their corresponding minimum values to the left (potential i values). As we scan from left to right, we maintain a stack of pairs [nums[j], minLeft] where minLeft is the smallest element seen before index j. When we encounter a new element, if it's greater than the minLeft of any stack entry but less than that entry's value, we found a valid 132 pattern.
Algorithm
- Initialize a stack to store pairs
[num, minLeft]and trackcurMinas the running minimum. - For each element starting from index 1:
- Pop elements from the stack while the current element is greater than or equal to the top.
- If the stack is not empty and the current element is greater than
stack.top().minLeft, returntrue. - Push the current element with
curMinonto the stack. - Update
curMinto be the minimum of itself and the current element.
- Return
falseif no pattern is found.
class Solution:
def find132pattern(self, nums: List[int]) -> bool:
stack = [] # pair [num, minLeft], mono decreasing
curMin = nums[0]
for i in range(1, len(nums)):
while stack and nums[i] >= stack[-1][0]:
stack.pop()
if stack and nums[i] > stack[-1][1]:
return True
stack.append([nums[i], curMin])
curMin = min(curMin, nums[i])
return FalseTime & Space Complexity
- Time complexity:
- Space complexity:
3. Stack (Optimal)
Intuition
We can solve this more elegantly by iterating from right to left. The key insight is to track k, which represents the largest valid "2" in a potential 132 pattern (the middle value that's smaller than some "3" to its right). We use a stack to maintain elements in decreasing order. When we find an element larger than the stack top, we pop elements and update k to be the largest popped value. If we ever find an element smaller than k, we've found our "1", completing the pattern.
Algorithm
- Initialize an empty stack and set
kto negative infinity. - Iterate from the end of the array to the beginning:
- If the current element is less than
k, returntrue(we found the "1"). - While the stack is not empty and the top is less than the current element:
- Pop and update
kto the popped value (this becomes a candidate for "2").
- Pop and update
- Push the current element onto the stack (candidate for "3").
- If the current element is less than
- Return
falseif no pattern is found.
Time & Space Complexity
- Time complexity:
- Space complexity:
4. Two Pointers
Intuition
We can achieve O(1) extra space by reusing the input array itself as a stack. The idea is the same as the optimal stack approach, but instead of using a separate stack, we use a pointer stkTop to track where our "stack" ends within the array. Elements from stkTop to n-1 form our virtual stack. This works because as we iterate from right to left, we no longer need the original values at those positions.
Algorithm
- Initialize
stkTopton(stack starts empty) andkto negative infinity. - Iterate from the end of the array to the beginning:
- If the current element is less than
k, returntrue. - While
stkTop < nand the current element is greater thannums[stkTop]:- Update
ktonums[stkTop]and incrementstkTop(pop from virtual stack).
- Update
- Decrement
stkTopand store the current element at that position (push to virtual stack).
- If the current element is less than
- Return
falseif no pattern is found.
class Solution:
def find132pattern(self, nums: List[int]) -> bool:
n = len(nums)
stkTop, k = n, float('-inf')
for i in range(n - 1, -1, -1):
if nums[i] < k:
return True
while stkTop < n and nums[i] > nums[stkTop]:
k = nums[stkTop]
stkTop += 1
stkTop -= 1
nums[stkTop] = nums[i]
return FalseTime & Space Complexity
- Time complexity:
- Space complexity: extra space.
Common Pitfalls
Confusing the Pattern Order
The "132 pattern" refers to the relative ordering of values, not indices. You need nums[i] < nums[k] < nums[j] where i < j < k. A common mistake is looking for values in the wrong order or confusing which index maps to which part of the pattern name.
Using Wrong Comparison Operators
The pattern requires strict inequalities: nums[i] < nums[k] < nums[j]. Using <= instead of < will incorrectly accept patterns where two elements are equal.
# Wrong: allows equal values
if nums[i] <= nums[k] <= nums[j]:
# Correct: requires strict inequalities
if nums[i] < nums[k] < nums[j]:Forgetting to Track the Minimum Correctly
In the stack-based approach, you must track the minimum value to the left of each potential "3" (middle element). Failing to update the minimum correctly or associating it with the wrong stack element leads to missing valid patterns or false positives.
Sign in to join the discussion