Documentation Index
Fetch the complete documentation index at: https://resources.devweekends.com/llms.txt
Use this file to discover all available pages before exploring further.
What is Monotonic Stack?
Monotonic Stack is a stack where the elements are always maintained in sorted order — either strictly increasing from bottom to top (monotonic increasing) or strictly decreasing (monotonic decreasing). Every time you push a new element, you first pop off anything that violates the ordering invariant. Think of it like a bouncer at a club with a height rule: “No one shorter than the person behind you is allowed to stay.” When a tall person arrives, the bouncer removes everyone shorter who is already in line. This “removal event” is exactly when we record an answer — the element being removed just found its “next greater element.” This pattern transforms what looks like an O(n^2) “for each element scan the rest of the array” problem into a clean O(n) solution, because every element is pushed and popped at most once.Pattern Recognition Cheatsheet
Reusable Template Code
Two skeletons — one for “next” problems (resolve on pop) and one for “previous” problems (resolve on push) — cover every monotonic-stack variant.When to Use
Next Greater Element
Previous Smaller
Histogram Problems
Stock Span
Pattern Variations
1. Next Greater Element
For each position, find the first element to its right that is larger. The brute-force approach scans rightward for every element (O(n^2)). With a monotonic decreasing stack, each element is pushed and popped at most once, giving O(n) total. Key insight: The stack holds indices of elements that have not yet found their “next greater.” When a new element arrives that is larger than the stack top, we have found the answer for that stack element. Complexity: O(n) time, O(n) space for the stack and result array.2. Previous Smaller Element
The mirror of “next greater” — for each element, find the nearest element to its left that is strictly smaller. We maintain a monotonic increasing stack (bottom to top). Before pushing the current element, we pop anything greater than or equal to it; whatever remains on top is the previous smaller element. Complexity: O(n) time, O(n) space.3. Largest Rectangle in Histogram
This is the canonical hard monotonic-stack problem. The idea: for each bar, find how far left and right it can extend as the shortest bar. The rectangle area for that bar isheight * width. A monotonic increasing stack (by height) lets us compute this efficiently.
When we encounter a bar shorter than the stack top, we pop and calculate the area for the popped bar — we know its right boundary (current index) and its left boundary (the new stack top). Anything left in the stack after the loop extends all the way to the right end.
Complexity: O(n) time, O(n) space.
Interview tip: This problem is the building block for “Maximal Rectangle” in a 2D matrix — you build a histogram per row and run this algorithm on each.
4. Daily Temperatures
A direct application of the “next greater element” pattern, except instead of recording the value of the next greater element, we record the distance (number of days to wait). The stack holds indices of days still waiting for a warmer day. Complexity: O(n) time, O(n) space.5. Trapping Rain Water
The stack-based approach processes water layer by layer (horizontally), unlike the two-pointer approach which works column by column. When we encounter a bar taller than the stack top, we know water is trapped between the current bar and the bar beneath the popped element. The water volume for that layer iswidth * bounded_height.
Complexity: O(n) time, O(n) space.
Interview tip: This problem has three valid approaches (stack, two-pointer, prefix-max arrays). Being able to discuss all three and their trade-offs signals strong problem-solving breadth. The two-pointer approach uses O(1) space and is covered in the Two Pointers chapter.
How to Choose Increasing vs Decreasing
The most confusing decision for beginners is which monotonic direction to use. Here is a simple rule:| You Want To Find | Stack Direction | Pop When |
|---|---|---|
| Next Greater | Decreasing (bottom-to-top) | Current element > stack top |
| Next Smaller | Increasing (bottom-to-top) | Current element less than stack top |
| Previous Greater | Decreasing, record on push | After popping, stack top is the answer |
| Previous Smaller | Increasing, record on push | After popping, stack top is the answer |
Worked LeetCode Problems: Brute Force vs Optimized
The four canonical monotonic-stack problems. Each one teaches a distinct twist on the same skeleton.LC 496: Next Greater Element I (Easy)
Problem. Given two arrays wherenums1 is a subset of nums2, find the next greater element in nums2 for each element in nums1.
Brute force (O(n * m)). For each nums1[i], find it in nums2 and scan rightward. Slow.
Optimized monotonic stack + map (O(n + m)). Pre-compute next greater for every element of nums2 using a monotonic decreasing stack, store results in a map, then look up nums1 answers in O(1) each.
LC 739: Daily Temperatures (Medium)
Problem. For each day, return how many days until a warmer temperature, or 0 if none. Brute force (O(n^2)). For each day, scan forward. Optimized monotonic stack (O(n)). Stack of indices — not values — so we can compute the day-distance.i - j to compute the distance, so we cannot afford to throw away positional information. This is the rule for the entire pattern: when in doubt, push indices.
LC 84: Largest Rectangle in Histogram (Hard)
Problem. Given an array of bar heights, find the area of the largest axis-aligned rectangle that fits within the histogram. Brute force (O(n^2)). For each pair (i, j), find the minimum height in [i, j] and compute area. Optimized monotonic increasing stack (O(n)). When we encounter a bar shorter than the stack top, the popped bar’s rectangle is finalized: its height isheights[popped], its width spans from one past the new stack top up to (but not including) the current index.
i - stack[-1] - 1, NOT i - top. The reason: previously-popped bars between stack[-1] and i were all taller than the popped bar, so the popped bar’s rectangle extends through them. Get this wrong and you systematically under-count area.
LC 42: Trapping Rain Water (Hard) — Stack Approach
Problem. Given an elevation map, compute total trapped rainwater. Brute force (O(n^2)). For each position, find max-left and max-right, water at i =min(max_left, max_right) - height[i].
Optimized — there are three valid approaches. Two-pointer (O(1) space), prefix arrays (O(n) space, easiest), and monotonic stack (O(n) space, processes water layer-by-layer). Mention all three; pick two-pointer in production unless asked otherwise.
Monotonic decreasing stack (O(n)). When a taller bar arrives, water is trapped between the current bar (right wall), the bar below the popped element (left wall), and the popped element itself (valley floor).
Caveats and Traps
Curated LeetCode Practice List
The classic monotonic-stack problem set, grouped by difficulty.Easy
| # | Problem | Pattern Variant |
|---|---|---|
| 496 | Next Greater Element I | Decreasing stack + map |
| 1475 | Final Prices With a Special Discount | Next smaller-or-equal element |
| 1063 | Number of Valid Subarrays | Previous smaller (premium) |
Medium
| # | Problem | Pattern Variant |
|---|---|---|
| 739 | Daily Temperatures | Decreasing stack of indices |
| 503 | Next Greater Element II | Circular array (iterate 2n) |
| 901 | Online Stock Span | Streaming monotonic decreasing |
| 856 | Score of Parentheses | Stack arithmetic on nesting |
| 1019 | Next Greater Node in Linked List | Same pattern, linked-list input |
| 402 | Remove K Digits | Greedy increasing-stack pop |
| 316 | Remove Duplicate Letters | Increasing stack + lookahead |
| 1856 | Maximum Subarray Min-Product | Span-as-minimum + prefix sum |
Hard
| # | Problem | Pattern Variant |
|---|---|---|
| 84 | Largest Rectangle in Histogram | Increasing stack + width formula |
| 85 | Maximal Rectangle | Per-row histogram |
| 42 | Trapping Rain Water | Decreasing stack horizontal layers |
| 907 | Sum of Subarray Minimums | Contribution + two passes |
| 2104 | Sum of Subarray Ranges | Max-sum minus min-sum |
| 1944 | Number of Visible People in a Queue | Monotonic + counting |
| 975 | Odd Even Jump | Two monotonic-stack passes + DP |
Classic Problems
| Problem | Stack Type | Key Insight |
|---|---|---|
| Next Greater | Decreasing | Pop smaller, push current |
| Previous Smaller | Increasing | Pop larger or equal |
| Histogram | Increasing | Calculate area on pop |
| Daily Temperatures | Decreasing | Store indices, compute diff |
| Stock Span | Decreasing | Count days with smaller price |
| Sum of Subarray Minimums | Increasing | Contribution technique — each element’s span |
Practice Problems
Next Greater Element I
Largest Rectangle
Trapping Rain Water
Sum of Subarray Mins
Interview Questions
1. Explain the monotonic stack pattern. Why does it reduce the “next greater element” problem from O(n^2) to O(n)?
What interviewers are really testing: Whether you understand the amortized argument — that each element is pushed and popped at most once — and can explain why the stack maintains its invariant. The O(n) claim without the proof is not enough. Strong Answer:- A monotonic stack maintains elements in sorted order (increasing or decreasing). For “next greater element,” we use a decreasing stack (bottom to top). We iterate through the array; for each new element, we pop all stack elements smaller than it — each popped element just found its next greater element (the current element).
- The O(n) proof: every element is pushed exactly once and popped at most once. Across the entire loop, we do at most n pushes and at most n pops, giving 2n total operations — O(n). The while loop inside the for loop is misleading; it looks nested, but the total work across all iterations is bounded by n pops.
- Think of it like a bouncer at a club with a height rule. When a tall person arrives, the bouncer removes everyone shorter in line. Each person enters and leaves the line at most once.
- After processing the entire array, any elements remaining on the stack have no next greater element — their answer is -1 (or whatever the default is).
- How would you modify this to find the “next greater or equal” element instead of “strictly greater”?
- If the array is circular (the element after the last wraps to the first), how do you adapt the monotonic stack approach?
2. When do you use an increasing vs. decreasing monotonic stack? Give the decision rule.
What interviewers are really testing: Whether you have internalized the pattern rather than memorizing individual problems. The ability to choose the correct stack direction from a problem statement is the skill that transfers across problems. Strong Answer:- The rule is: the stack direction is opposite to what you are searching for. Looking for the “next greater”? You need elements waiting on the stack to be in decreasing order, so that a larger arriving element triggers resolution. Looking for the “next smaller”? You need increasing order, so that a smaller element triggers resolution.
- For “next” problems (looking rightward), the answer is found on pop — the popped element found its answer when a new element violated the stack’s ordering. For “previous” problems (looking leftward), the answer is found on push — whatever remains on the stack top after popping is the nearest element in that direction.
- Concrete mapping: Next Greater = decreasing stack, pop when current is greater than top. Next Smaller = increasing stack, pop when current is less than top. Previous Greater = decreasing stack, answer is stack top before pushing. Previous Smaller = increasing stack, answer is stack top before pushing.
- Memory trick I use: “Next resolves on pop, Previous resolves on push.” This one-liner covers all four variants.
- For the “Sum of Subarray Minimums” problem, you need both the previous smaller and next smaller element for each position. How do you combine two monotonic stack passes?
- What happens with duplicate values? Does “strictly less than” vs “less than or equal” in the pop condition change which stack direction you use?
3. Walk me through how the “Largest Rectangle in Histogram” problem works with a monotonic stack.
What interviewers are really testing: This is the canonical hard monotonic stack problem. They want to see if you can explain the left/right boundary logic, the area calculation on pop, and how thestart index tracks how far each bar extends backward.
Strong Answer:
- The core idea: for each bar, find how far it can extend left and right as the shortest bar. The rectangle area for that bar is
height * (right_boundary - left_boundary). A monotonic increasing stack (by height) lets us compute both boundaries efficiently. - We maintain a stack of
(start_index, height)pairs in increasing order of height. When we encounter a bar shorter than the stack top, we pop — the popped bar can no longer extend right (the current bar blocks it). Its area isheight * (current_index - start_index). Crucially, the current shorter bar can extend back to where the popped bar started, so we trackstart = popped.start_index. - After processing all bars, anything left on the stack extends all the way to the right edge of the histogram. For each remaining
(start, height), the area isheight * (n - start). - Example: heights
[2, 1, 5, 6, 2, 3]. The largest rectangle is height 2, spanning indices 0-5, giving area 26 = 12. Wait — actually it is height 5 spanning indices 2-3, area 10? Let me recheck: height 2 from index 0 to 5 gives 26=12. But the bar at index 1 has height 1, which blocks the height-2 bar. The actual answer is 10 (height 5 across indices 2-3). This kind of careful walkthrough is what interviewers want to see.
start index carries backward from popped elements, not from the current index.
Follow-ups:
- How do you extend this to “Maximal Rectangle” in a 2D binary matrix?
- Could you solve this problem with a divide-and-conquer approach? What would the complexity be?
4. Solve “Daily Temperatures” — for each day, find how many days until a warmer temperature. How is this different from “Next Greater Element”?
What interviewers are really testing: Whether you can recognize that this is a direct application of the monotonic stack “next greater” pattern and adapt it to return distances instead of values. Simple but tells the interviewer if you pattern-match effectively. Strong Answer:- This is exactly the “Next Greater Element” pattern, but instead of recording the value of the next greater element, we record the distance (index difference). The stack holds indices of days still waiting for a warmer day.
- Iterate through temperatures. For each day
i, while the stack is non-empty andtemperatures[i] > temperatures[stack.top()], pop the top indexidxand setresult[idx] = i - idx. Then pushi. - Days remaining on the stack after the loop never find a warmer day, so their result stays 0 (the default).
- The structural difference from the basic “Next Greater Element” is purely in what we record:
result[idx] = nums[i](value) vs.result[idx] = i - idx(distance). The stack logic is identical. Recognizing this mapping is the skill — once you see it, the problem is a 5-minute solve.
- What if we also need to find how many days until a cooler temperature? How does the stack direction change?
- Can you solve this problem in O(n) time with O(1) extra space (not counting the output array)? Hint: traverse from right to left.
5. Explain how the stack-based approach for “Trapping Rain Water” works. How does it differ from the two-pointer approach?
What interviewers are really testing: Whether you can explain two fundamentally different approaches to the same problem and compare their trade-offs. Being able to discuss multiple solutions and their mental models is a senior-level signal. Strong Answer:- The stack approach processes water horizontally, layer by layer. We maintain a decreasing stack of bar indices. When we encounter a bar taller than the stack top, water is trapped between the current bar (right wall) and the bar below the popped element (left wall). The water volume for that layer is
width * bounded_height, wherewidth = i - stack.top() - 1andbounded_height = min(height[i], height[stack.top()]) - height[popped]. - The two-pointer approach processes water vertically, column by column. Two pointers start at both ends, and we track
left_maxandright_max. At each step, move the pointer with the smaller max inward. The water above the current bar ismax_on_its_side - height[current]. - Trade-off: the stack approach uses O(n) space and is harder to implement correctly (the three-element interaction of current, popped, and stack top is error-prone). The two-pointer approach uses O(1) space and is conceptually elegant. Both are O(n) time.
- There is also a third approach: build
left_max[]andright_max[]prefix/suffix arrays, then for each bar, water =min(left_max[i], right_max[i]) - height[i]. This is O(n) time and O(n) space — easiest to understand, moderate space.
height[popped] for the valley floor.
Follow-ups:
- Why does the two-pointer approach move the pointer with the smaller max? What breaks if you move the other one?
- Can this problem be extended to 3D (trapping water on a 2D elevation map)? What data structure would you use?
6. What is the “contribution technique” used in “Sum of Subarray Minimums”? How does a monotonic stack enable it?
What interviewers are really testing: This is a staff-level question that tests whether you can think about each element’s individual contribution to the total rather than iterating over all subarrays. The monotonic stack is the tool, but the insight is the contribution decomposition. Strong Answer:- Instead of finding the minimum of every subarray (O(n^2) subarrays), we flip the question: for each element
nums[i], in how many subarrays is it the minimum? Its contribution to the total sum isnums[i] * count_of_subarrays_where_it_is_minimum. - To count those subarrays, we need to find how far left and right
nums[i]extends as the minimum. Letleft[i]= distance to the previous smaller element, andright[i]= distance to the next smaller (or equal) element. The number of subarrays wherenums[i]is the minimum isleft[i] * right[i]. - We use two monotonic stack passes: one left-to-right for
previous smaller(increasing stack), one right-to-left fornext smaller or equal(increasing stack). The “or equal” on one side prevents double-counting when duplicate values exist. - Total sum = sum of
nums[i] * left[i] * right[i]for all i. Time is O(n), space is O(n). This technique generalizes to “Sum of Subarray Maximums,” “Sum of Subarray Ranges,” and similar problems.
- Why does one boundary use strict less-than and the other uses less-than-or-equal? What happens if you use strict less-than on both?
- How would you adapt this technique to compute “Sum of Subarray Ranges” (max - min for every subarray)?
7. You have a circular array and need to find the next greater element for each position, where the search wraps around. How do you handle this?
What interviewers are really testing: Whether you can extend the linear monotonic stack to handle circular arrays. The standard trick is conceptually simple but tests whether you have seen enough variations to know it. Strong Answer:- The trick is to iterate through the array twice (indices 0 to 2n-1) and use
i % nto get the actual index. This simulates the circular wrap-around. In the first pass, elements find their next greater if it exists to the right. In the second pass, elements that wrap around find their next greater from the beginning of the array. - We only push indices during the first pass (when
iis less thann) to avoid duplicating entries. During the second pass, we only pop and resolve — we do not push new indices because those are duplicates. - Actually, the cleaner implementation pushes
i % nfor alliin[0, 2n)and checksstackelements as usual, but only initializes the result array with -1 for size n. Each element can be pushed up to twice and popped up to twice, so total operations are O(n). The result array only stores answers for the original n positions. - Example:
[2, 1, 2, 4, 3]— the element 3 at index 4 has no next greater in the linear case (-1), but in the circular case, wrapping around, its next greater is 4 at index 3.
- Does the circular approach change the time complexity? What about space?
- Can you think of a problem where the circular monotonic stack variant is useful in a real system (not just a LeetCode exercise)?
Interview Deep-Dive
You are given an array of building heights. For each building, find the area of the largest rectangle that includes that building as the shortest bar and extends continuously in both directions. How do you solve this in O(n)?
You are given an array of building heights. For each building, find the area of the largest rectangle that includes that building as the shortest bar and extends continuously in both directions. How do you solve this in O(n)?
- This is exactly the histogram rectangle problem. For each bar, I need to find how far left and right it can extend as the shortest bar. The rectangle area for that bar is
height[i] * (right_boundary - left_boundary). - I maintain a monotonic increasing stack (by height). When I encounter a bar shorter than the stack top, I pop. The popped bar’s right boundary is the current index (the first shorter bar to the right), and its left boundary is the new stack top (the first shorter bar to the left). The width is
current_index - stack_top - 1. - The key insight people miss: when I pop a bar and compute its area, the current shorter bar can extend backward to where the popped bar started. So I track a
startindex that carries backward through successive pops. This means the current bar’s effective left boundary may be far to the left of its actual position. - After processing all bars, anything remaining on the stack extends to the right edge. For each remaining
(start, height), the area isheight * (n - start). - Time is O(n) because each bar is pushed and popped at most once. Space is O(n) for the stack.
matrix[i][j] = 1, then heights[j] = heights[j] + 1 (building up from the previous row). If matrix[i][j] = 0, then heights[j] = 0 (the column is broken). Then run the 1D histogram algorithm on each row’s heights. The overall answer is the maximum across all rows. Total time is O(m * n) where m is rows and n is columns — you do O(n) histogram work for each of m rows. This is LeetCode 85 (Maximal Rectangle), and it is the canonical example of reducing a 2D problem to repeated applications of a 1D technique.Given an array of integers, compute the sum of (minimum of every subarray). Each element contributes to many subarrays as the minimum. How do you avoid the O(n^2) enumeration?
Given an array of integers, compute the sum of (minimum of every subarray). Each element contributes to many subarrays as the minimum. How do you avoid the O(n^2) enumeration?
- The key insight is to compute each element’s “span” as the minimum. For element
nums[i], findleft[i]= the number of consecutive elements to the left that are greater than or equal tonums[i](inclusive ofiitself), andright[i]= the number of consecutive elements to the right that are strictly greater. The number of subarrays wherenums[i]is the minimum isleft[i] * right[i]. - I use two monotonic stack passes: one left-to-right with an increasing stack to find the “previous smaller element” distance for each position, and one right-to-left with an increasing stack to find the “next smaller or equal element” distance.
- The critical subtlety is handling duplicates. If I use strict less-than on both sides, I will double-count subarrays where two equal elements are both “the minimum.” The fix: use strict less-than on one side (say, left) and less-than-or-equal on the other (right). This assigns each subarray to exactly one element as its “responsible minimum.”
- Total sum =
sum(nums[i] * left[i] * right[i])for all i. Time is O(n) for two passes, space is O(n) for the stack and boundary arrays.
Sum of Ranges = Sum of Subarray Maximums - Sum of Subarray Minimums. You already know how to compute the sum of subarray minimums with the contribution technique. The sum of subarray maximums is the mirror: use a monotonic decreasing stack instead of increasing, find each element’s span as the maximum, and sum nums[i] * left_max[i] * right_max[i]. Both passes are O(n), so the total is O(n). This decomposition is the standard approach for LeetCode 2104 (Sum of Subarray Ranges).An interviewer asks: you have a stream of stock prices arriving one per day. For each day, compute the stock span -- the number of consecutive days (going backward, including today) where the price was less than or equal to today's price. Design an API that handles each new price in O(1) amortized time.
An interviewer asks: you have a stream of stock prices arriving one per day. For each day, compute the stock span -- the number of consecutive days (going backward, including today) where the price was less than or equal to today's price. Design an API that handles each new price in O(1) amortized time.
- This is the “previous greater element” pattern adapted as a streaming API. I maintain a monotonic decreasing stack of
(price, span)pairs. The stack invariant: prices are in decreasing order from bottom to top. - When a new price arrives, I initialize its span as 1. Then I pop all stack elements whose price is less than or equal to the new price, adding their spans to the current span. This is because if the new price is higher, it “absorbs” all those consecutive days. Then I push
(new_price, accumulated_span)onto the stack. - Each element is pushed exactly once and popped at most once across all calls, so the amortized cost per
next()call is O(1), even though a single call might pop many elements. - The API looks like:
- This is O(1) amortized time per call and O(n) total space for n calls. In a real trading system, you might cap the stack size to limit memory, accepting that spans beyond a certain window are truncated.
next() computes a span, update max_span = max(max_span, span). This adds O(1) work per call and O(1) space. The trick is that this is a monotonically non-decreasing value — once a large span is seen, it can only be equaled or exceeded, never reduced. If instead they asked for the maximum span within the last K days (a sliding window over spans), you would need a monotonic deque on the span values, which is the “Sliding Window Maximum” pattern applied to the stream of spans.Compare three approaches for Trapping Rain Water: monotonic stack, two pointers, and prefix arrays. When would you pick each one in an interview?
Compare three approaches for Trapping Rain Water: monotonic stack, two pointers, and prefix arrays. When would you pick each one in an interview?
- Prefix arrays (left_max / right_max): Build
left_max[i]= max height from index 0 to i, andright_max[i]= max height from i to n-1. Water at each index ismin(left_max[i], right_max[i]) - height[i]. Time O(n), space O(n). This is the easiest to understand and implement. I would pick this if I want a quick, bug-free solution and do not care about O(n) space. - Two pointers: Two pointers start at both ends, tracking
left_maxandright_max. Move the pointer with the smaller max inward. Water at the current position ismax_on_its_side - height[current]. Time O(n), space O(1). This is the most elegant and space-efficient. I would pick this if the interviewer cares about space optimization or if I want to impress with a clean single-pass solution. - Monotonic stack: Maintain a decreasing stack of indices. When a taller bar arrives, pop and compute water layer by layer (horizontally). Time O(n), space O(n) for the stack. This is the hardest to get right — the three-element interaction (current bar, popped bar, new stack top) is error-prone. I would pick this only if the interviewer specifically asks for a stack-based solution, or if the problem is a variant where the stack approach generalizes better (like computing water in a 3D terrain using a priority queue extension).
- My recommendation in a real interview: Start with the prefix array approach to show understanding. Then mention the two-pointer optimization to show you can reduce space. If time remains, mention the stack approach as an alternative mental model. This demonstrates breadth without risking a buggy implementation.
max(0, current_wall_height - neighbor_height). Push the neighbor into the heap with max(current_wall_height, neighbor_height) as its effective wall height. This is a BFS-like expansion from the boundary inward, always processing the lowest wall first. Time is O(mn log(mn)), space is O(mn). The prefix array and stack approaches do not generalize cleanly to 2D because the water at each cell is bounded by walls from all directions, not just left and right.Interview Q&A Rapid-Fire (Rich Format)
The four questions below are FAANG-favorite monotonic-stack problems. Each one includes a strong answer framework, a real LeetCode example with full code, three senior follow-ups in<Note> blocks, common wrong answers, and further reading.
Q1: Daily Temperatures explained -- the canonical monotonic stack
Q1: Daily Temperatures explained -- the canonical monotonic stack
- Recognize the pattern. “This is the ‘next greater element’ template — I am looking for the first day to my right with a higher temperature.”
- Reject the brute force. O(n^2) — for each day scan forward. Times out for inputs over 10000.
- Introduce the monotonic decreasing stack of indices. Days waiting for a warmer future sit on the stack in non-increasing order of temperature.
- Walk through the resolve-on-pop step. When today is warmer than the day on top, pop and record
today_index - popped_index. - Prove the O(n) amortized cost. Each index pushed once, popped at most once — 2n operations total.
i - j, the day distance. The values themselves are recoverable via temps[stack[-1]]. Default to indices in every monotonic-stack problem; it is the lossless choice.i, jump forward using already-computed answers: if result[i + 1] says “wait k days,” and day i + 1 + k is still not warmer than i, jump again using result[i + 1 + k]. Each jump skips a known-cold range. Total work is amortized O(n).(price, span) pairs. On a new price, accumulate the spans of all popped smaller-or-equal prices. Amortized O(1) per call.- “Brute force forward scan” — O(n^2), fails on large inputs.
- “Push values instead of indices” — cannot compute the distance.
- “Use a monotonic increasing stack” — finds next smaller day, not warmer day. Direction matters.
Q2: Trapping Rain Water -- two-pointer AND monotonic-stack approaches
Q2: Trapping Rain Water -- two-pointer AND monotonic-stack approaches
- Mention all three approaches. Prefix arrays (O(n) space, easiest), two-pointer (O(1) space, most elegant), monotonic stack (O(n) space, processes water in horizontal layers). Discussing breadth is the senior signal.
- Code the two-pointer first if asked for the cleanest solution.
- Pivot to the stack version if asked for an alternative or for the streaming case.
- Explain the two-pointer invariant. “If
left_max <= right_max, water at the left position is bounded byleft_max. The pointer with the smaller max can safely commit and move.” - Explain the stack version. “When a taller bar arrives, water is trapped between the current bar (right wall), the new stack top after popping (left wall), and the popped element (valley floor).”
min(left_max, right_max) = left_max (when left is smaller). So we can commit the water amount and advance.max(0, current_wall - neighbor_height). Push neighbor with max(current_wall, neighbor_height) as its effective wall.- Knowing only one approach. Interviewers love to ask “can you do it differently?” — if you only know the stack version, you will struggle.
- In the stack version,
width = i - popped_indexinstead ofi - stack[-1] - 1. Off-by-one bug. - In the two-pointer version, moving the wrong pointer when maxes are equal — the algorithm still works, but careless reasoning about why is a red flag.
- LC 42: Trapping Rain Water
- LC 407: Trapping Rain Water II (2D)
- LC 11: Container With Most Water (similar two-pointer geometry)
Q3: Largest Rectangle in Histogram
Q3: Largest Rectangle in Histogram
- State the goal. “For each bar, find how far left and right it can extend as the shortest bar in the rectangle. Area = height * (right_boundary - left_boundary).”
- Maintain a monotonic increasing stack of indices.
- Resolve on pop. When a shorter bar arrives, the popped bar’s right boundary is the current index, and its left boundary is the new stack top after popping (or -1 if empty).
- The width formula.
width = i - stack[-1] - 1(oriif stack is empty). Noti - popped. - Use a sentinel. Append
0to the heights array to force a final flush.
i - stack[-1] - 1 and not i - top?” — Because previously-popped bars between the new stack top and i were ALL taller than the popped bar. So the popped bar’s rectangle of its own height extends through all of them. Get this wrong and you systematically under-count area.width = n - stack[-1] - 1 (or n if stack now empty). Same logic, just written twice. Sentinel is cleaner; cleanup loop is more explicit. Both work.- “Width is
i - popped_index.” Wrong by missing the previously-popped contributions. - “Use a monotonic decreasing stack.” Wrong direction — pops would happen on smaller arrivals, not larger.
- “Brute force every (i, j) pair.” O(n^2) with min-finding inside; O(n^3) naive. Fails the constraint.
Q4: Sum of Subarray Minimums -- the contribution technique
Q4: Sum of Subarray Minimums -- the contribution technique
- Flip the perspective. Instead of “for each subarray find its min”, ask “for each element, in how many subarrays is it the min?”
- Compute span boundaries. For element
nums[i], findleft[i]= distance to nearest strictly smaller on the left, andright[i]= distance to nearest smaller-or-equal on the right. The number of subarrays wherenums[i]is the min isleft[i] * right[i]. - Two monotonic stack passes. One left-to-right (increasing stack) for previous-smaller, one right-to-left for next-smaller-or-equal.
- Justify the asymmetric strict/non-strict. With duplicates, using strict
<on both sides causes double-counting subarrays where two equal elements both qualify. Make one side non-strict to break the tie deterministically. - Sum it up. Total = sum of
nums[i] * left[i] * right[i]. Time O(n), space O(n).
arr = [1, 2, 1]. Without the asymmetry, the subarray [1, 2, 1] is counted twice (once for each 1 as the min). The asymmetry assigns each subarray to exactly one “responsible minimum” — typically the leftmost or rightmost occurrence.- “Iterate every subarray and sum the min” — O(n^2) at minimum, often O(n^3); times out.
- “Use strict inequality on both sides” — double-counts subarrays with duplicate minimums.
- “Forget the modulo” — LC 907 specifically requires
% (10^9 + 7).