Stacks and Monotonic Structures
34 / 170Stacks and Monotonic StructuresLesson 4 of 8About 69 min
The unit's central idea: throw away every candidate that can never be the answer, and what remains is sorted for free.
A large family of problems asks, for each position, about the nearest position in some direction with a particular relationship to it. The nearest larger value to the left. The nearest smaller value to the right. How far you can extend before something blocks you.
The brute force scans outward from every position, which is O(n squared). The fix is not a better scan. It is noticing that most positions are permanently useless as answers and can be discarded.
Run next_greater on [2, 1, 2, 4, 3]. For each step give what the stack holds after processing that index, as a list of indexes like [0, 1], and which indexes got resolved at that step, as a list like [1] or [].
| i | value | resolved this step | stack after |
|---|---|---|---|
| 0 | 2 | ||
| 1 | 1 | ||
| 2 | 2 | ||
| 3 | 4 |
Write two of the four boundary questions, then use one. previous_smaller returns, for each index, the index of the nearest earlier position with a strictly smaller value, or -1. next_smaller returns the nearest later position with a strictly smaller value, or the length of the list when there is none. widest_span uses both to report, for each index, how far its value extends before something smaller blocks it on either side.
Tests
print(previous_smaller([2, 1, 5, 6, 2, 3]))print(next_smaller([2, 1, 5, 6, 2, 3]))print(widest_span([2, 1, 5, 6, 2, 3]))Output
Run tests to see output.
Read the constraints first and let them tell you what complexity is expected. Derive the approach, implement it, run the tests, and submit when it passes.