456. 132 Pattern

URL: https://leetcode.com/problems/132-pattern
Difficulty: Medium

Even though the tag of this problem is “Binary Search”,
you can solve this problem without using binary search.
However, it is a problem that can be solved by using a stack.
But, although it can be expressed in a simple code, I could not solve it in the end.
In order to be accepted, you need to implement it in O(N), but I could not reach that point.
This time, I would like to explain based on the answer of NeetCode’s answer.

Reference Code: 132 Pattern - Leetcode 456 - Python - YouTube

Description

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.

Code

# To run this code localy,
# I changed the argument of the function to nums.
def find132pattern(nums):
  stack = []
  curMin = nums[0]
  for n in nums[1:]:
    while stack and n >= stack[-1][0]:
      stack.pop()
    if stack and n > stack[-1][1]:
      return True
    stack.append([n,curMin])
    curMin = min(curMin,n)
  return False

Steps to solve

① Determine stack and minimum value with initial values
② Create a for loop
③ Store values in the stack
④ Update the minimum value
⑤ Take values out of the stack
⑥ Check if 132 pattern exists

① Determine stack and minimum value with initial values

stack:
Make a stack to store values.
The initial value is an empty list.

curMin:
Make a variable to store the current minimum value.
The initial value is the first element of the array.

def find132pattern(nums):

  # Make variables
  stack = [] # Initialize stack with empty list
  curMin = nums[0] # Initialize curMin with the first element of the array

② Create a for loop

The range is from the second element of the array to the end.
The reason why the range is from the second element of the array is because we have already stored the first element in curMin.

def find132pattern(nums):
  stack = []
  curMin = nums[0]

  # Create a for loop
  for n in nums[1:]:

③ Store values in the stack

In the first loop, [2,1] is stored in stack,
stack = [[2,1]]

def find132pattern(nums):
  stack = []
  curMin = nums[0]

  for n in nums[1:]:

    # Store values in the stack
    stack.append([n,curMin])

④ Update current minimum value

Compare n and curMin just added to the stack,
and update curMin to n if n is smaller.

def find132pattern(nums):
  stack = []
  curMin = nums[0]

  for n in nums[1:]:
    stack.append([n,curMin])

    # Update current minimum value
    curMin = min(curMin,n)

⑤ Take values out of the stack

Compare n and the 0th element of the last element of the stack.
If n is greater than or equal to the 0th element of the last element of the stack, take the value out of the stack.

def find132pattern(nums):
  stack = []
  curMin = nums[0]

  for n in nums[1:]:

    # Take values out of the stack
    while stack and n >= stack[-1][0]:
      stack.pop()

    stack.append([n,curMin])
    curMin = min(curMin,n)

⑥ Check if 132 pattern exists

Finally, implement the 132 pattern judgment.
Compare n and the 1st element of the last element of the stack.
If n is greater than the 1st element of the last element of the stack, 132 pattern exists. Then return True.

def find132pattern(nums):
  stack = []
  curMin = nums[0]

  for n in nums[1:]:
    while stack and n >= stack[-1][0]:
      stack.pop()

    # Check if 132 pattern exists
    if stack and n > stack[-1][1]:
      return True

    stack.append([n,curMin])
    curMin = min(curMin,n)
  return False

Let’s see the process of each loop

Let’s say nums = [1,2,0,3,-1,6,3].
Let’s see the actual processing of each loop.
The idea is to store the left value (minimum value of 132 pattern) and the middle value (maximum value of 132 pattern) in the stack for each loop, and judge it with the value of nums as the right value (intermediate value of 132 pattern).

nums = [1,2,0,3,-1,6,3]
  ...
  for n in nums[1:]:
  
    ## 1st loop
    # stack = [], curMin = 1, n = 2
    while stack and n >= stack[-1][0]: # False: stack is empty
      stack.pop()
    if stack and n > stack[-1][1]: # False: stack is empty
      return True
    stack.append([n,curMin]) # Update stack-> [[2,1]]
    curMin = min(curMin,n) # Update curMin -> 1
  
    ## 2nd loop
    # stack = [[2,1]], curMin = 1, n = 0
    while stack and n >= stack[-1][0]: # False: 0 >= 2
      stack.pop()
    if stack and n > stack[-1][1]: # False: 0 > 1
      return True
    stack.append([n,curMin]) # Update stack -> [[2,1],[0,1]]
    curMin = min(curMin,n) # Update curMin -> 0

    ## 3rd loop
    # stack = [[2,1],[0,1]], curMin = 0, n = 3
    while stack and n >= stack[-1][0]: # True: 3 >= 0 | True: 3 >= 2
      stack.pop() # Pop stack twice -> stack = []
    if stack and n > stack[-1][1]: # False: stack is empty
      return True
    stack.append([n,curMin]) # Update stack -> [[3,0]]
    curMin = min(curMin,n) # Update curMi -> 0

    ## 4th loop
    # stack = [[3,0]], curMin = 0, n = -1
    while stack and n >= stack[-1][0]: # False: -1 >= 3
      stack.pop()
    if stack and n > stack[-1][1]: # False: -1 > 0
      return True
    stack.append([n,curMin]) # Update stack -> [[3,0],[-1,0]]
    curMin = min(curMin,n) # Update curMin -> -1
  
    ## 5th loop
    # stack = [[3,0],[-1,0]], curMin = -1, n = 6
    while stack and n >= stack[-1][0]: # True: 6 >= -1 | True: 6 >= 3
      stack.pop() # Update stack / 2回pop() -> []
    if stack and n > stack[-1][1]: # False: stack is empty
      return True
    stack.append([n,curMin]) # Update stack -> [[6,-1]]
    curMin = min(curMin,n) # Update curMin -> -1
  
    ## 6th loop
    # stack = [[6,-1]], curMin = -1, n = 3
    while stack and n >= stack[-1][0]: # False: 3 >= 6
      stack.pop()
    if stack and n > stack[-1][1]: # True: 3 > -1
      return True # Found 132 pattern with [-1,6,3] / return True
    
  return False