456 132 Pattern
这题应用了monotonic stack, 但是相当tricky.
Approch 1: Monotonic Stack
需要在数组nums中,发现符合一下条件:
i < j < j and nums[i] < nums[k] < nums[j]
visualize一下,是找个如下图的山峰,

Therefore, 我们把这个问题分为两个子问题,
- 找到
nums[k] < nums[j]andj > k(等价于next smaller element) - 找到
nums[i] < nums[k]andi < j
所以我们需要维护
- Traverse
nums[k], 一个升序单调栈,让每次进来的nums[k]进来找老大. - 一个
prev_min数组,记录每个nums[k]左边的数组nums[:k]的最小值 (not includingnums[k])
这样只要每次我们进来的nums[k]找到了老大nums[j],我们就可以比较nums[:j]中的最小值,是否小于nums[k].
Code Implementation
class Solution:
def find132pattern(self, nums: List[int]) -> bool:
# maintaining a monotonically stack that we have a value that's smaller than it
"""
x
x
x
next greater element: maintain 升序单调stack
next smaller element: maintain 降序单调stack
我们这一题维护的是,
1. nums[k], 也就是第三个数. 对于nums[k]是否存在一个打不过的老大也就是stack中还有新来的nums[k]打不过的数. 这个老大也就是nums[j]
2. 找到老大之后,我们看这个老大的左边,有没有比它弱的数字nums[i].
"""
# preprocessing a hash for lookup:
prev_min = [None for _ in range(len(nums))]
prev_min[0] = max(nums)+1
for i in range(1,len(nums)):
prev_min[i] = min(prev_min[i-1],nums[i-1])
# traverse the list until found
stack = []
for k in range(len(nums)):
# try to find boss (nums[j])
while stack and nums[k] >= nums[stack[-1]]:
stack.pop()
# we find the boss (nums[j])! let's find the nums[i] that's the weakest
if stack and nums[k] > prev_min[stack[-1]]:
return True
# append the stack
stack.append(k)
return False