Monotonic Stack
Video: https://www.youtube.com/watch?v=7QEIZy1pp2o
Target problems:
- Find smaller/greater element to the right/left of the current element
The key is to understand what does stack[-1] represents
Next Greater Element problem
Template:1
2
3
4
5
6
7
8
9
10
11
12def nextGreaterElement(nums):
res = [0 for _ in range(len(nums))]
stack = []
for i in reversed(range(len(nums))):
while stack and nums[i] >= stack[-1]: # increasing stack
stack.pop()
if not stack:
res[i] = -1
else:
res[i] = stack[-1]
stack.append(nums[i])
return res
Leetcode 496. Next Greater Element I
Leetcode: https://leetcode.com/problems/next-greater-element-i/
- Strictly decreasing stack
stack[-1]
means the closest larger element to the right
1 | def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]: |
Leetcode 503. Next Greater Element II
Leetcode: https://leetcode.com/problems/next-greater-element-ii/
In the brute force way, we will go on to check num[i+2], num[i+3]… and there is much redundant work here. The better way is to check the next greater number of num[i+1]. If the next greater number of num[i+1] is still not greater than num[i], go on to check its next greater number.
1 | def nextGreaterElements(self, nums: List[int]) -> List[int]: |
739. Daily Temperature
- Stack can store additional data (index, etc)
1 | def dailyTemperatures(self, T: List[int]) -> List[int]: |
Area problem
42. Trapping Rain Water
Leetcode: https://leetcode.com/problems/trapping-rain-water/
- DP solution: 想象一束光分别从左边和右边照过array,阴影重叠部分即为积水面积
1 | def trap(self, height: List[int]) -> int: |
- Monotonic stack solution
- Note: Go from left to right and backwards, and keep finding left and right boundaries
- stack stores index of decreasing heights
1 | def trap(self, height: List[int]) -> int: |
Leetcode 84. Largest Rectangle in Histogram
Leetcode: https://leetcode.com/problems/largest-rectangle-in-histogram/
- Find smaller element in both left and right direction
- 递增的时候不算面积,递减的时候算面积
- For each pop round:
area = min_popped_height * (max_poped_index - last_popped_index - 1)
1 | def largestRectangleArea(self, heights: List[int]) -> int: |
Leetcode 85. Maximal Rectangle
Leetcode: https://leetcode.com/problems/maximal-rectangle/
- Repeat the solution in the problem 84 on every row
1 | def maximalRectangle(self, matrix: List[List[str]]) -> int: |
Leetcode 1504. Count Submatrices With All Ones
Leetcode: https://leetcode.com/problems/count-submatrices-with-all-ones/
Solution: https://leetcode.com/problems/count-submatrices-with-all-ones/discuss/720265/Java-Detailed-Explanation-From-O(MNM)-to-O(MN)-by-using-Stack
O(M N M) solution:
- Use a
high
andlow
boundaries,h[k] == 1
means all elements in columnk
betweenhight
andlow
are 1s - Adding a new 1 to a 1-D array: would add
len(arr)
new rectangles
1 | def numSubmat(self, mat: List[List[int]]) -> int: |
Optimize with Monotonic Stack
1 | # TBA |
Similar question:
- Number of Submatrices That Sum to Target
- Max Sum of Rectangle No Larger Than K
Monotonic Queue
239. Sliding Window Maximum
Leetcode: https://leetcode.com/problems/sliding-window-maximum/
- Construct a queue with decreasing order
- In the queue also store the index of current number so that we know if the boundary is reached and we need to
popleft
the item
1 | def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: |
1499. Max Value of Equation
Leetcode: https://leetcode.com/problems/max-value-of-equation/
Solution same as 239.
1 | def findMaxValueOfEquation(self, points: List[List[int]], k: int) -> int: |