Theory · Miscellaneous / Mixed Patterns
DSA Roadmap Open Visualizer Back to intro

Algocraft · Theory

When one pattern isn't enough

Every other theory page on this site covers one clean category — Trees, Heaps, Sliding Window, and so on. But plenty of real interview problems refuse to sit inside a single category. They ask for two different kinds of efficiency at once, and no single pattern delivers both. The skill being tested in those problems isn't knowledge of some exotic new algorithm — it's recognizing which two ordinary techniques need to work together, and wiring them up so each one does the part it's actually good at.

01 · Recognition

How to spot a mixed-pattern problem

Before reaching for anything exotic, interrogate the problem with a short set of questions. If more than one of these comes back "yes," you're very likely looking at a combo, not a single pattern:

The fix, once you notice two "yes" answers, is almost never to invent a new all-in-one algorithm. It's to pick the two matching techniques from the pages you already know and combine them — each one covering the requirement the other one can't.

02 · Combo #1

LRU Cache: Linked List + Hashmap

Primary: Linked Lists Secondary: Hashmap

A hashmap alone gives you O(1) lookup by key, but it has no built-in notion of "which entry was used least recently" — dictionaries don't remember access order in a way you can cheaply query and reorder. A doubly-linked list alone gives you O(1) removal and reordering of nodes, but finding which node corresponds to a given key means walking the list — O(n).

Put them together and each covers the other's gap: a hashmap maps key → node for instant lookup, while a doubly-linked list keeps every node ordered from most- to least-recently-used. get(key) uses the hashmap to jump straight to the node, then unlinks and re-inserts it at the "most recent" end of the list. put(key, value) does the same insert-or-update, and if the cache is now over capacity, it evicts whatever sits at the "least recent" end — again in O(1), because the linked list already knows exactly which node that is. Neither structure alone can do this in constant time; together, both operations are O(1).

Linked List O(1) reorder & eviction Hashmap O(1) lookup by key LRU Cache get() & put() both O(1)

Neither structure alone gets you O(1) on both operations — the overlap is where the actual LRU Cache lives.

See it built step by step in the LRU Cache visualizer, or read the deeper mechanics of the list side in the Linked List theory page.

03 · Combo #2

Sliding Window Maximum: Sliding Window + Monotonic Deque

Primary: Sliding Window Secondary: Monotonic Stack

A plain sliding window is great at tracking a moving range efficiently — add one element on the right, drop one on the left, all in O(1) per step. But if you need the maximum value inside that window at every step, and you find it by scanning the whole window each time, you're back to O(k) per step and O(n·k) overall — the windowing didn't actually save you anything for this particular question.

The fix is to keep a monotonic deque alongside the window: a double-ended queue of indices, kept in decreasing order of their values. Before pushing a new index, pop off anything smaller from the back (it can never be the max again while a bigger, more recent value is in the window). Pop from the front whenever the index there has slid out of the window. The front of the deque is then always the max of the current window, retrievable in O(1) — and because each index is pushed and popped at most once across the entire pass, the whole algorithm stays O(n), not O(n·k).

Watch this in action in the Sliding Window Maximum visualizer. For the windowing half, see the Sliding Window theory page; the monotonic-deque trick itself is a direct borrow from the monotonic stack idea covered on the Stack theory page.

04 · Combo #3

Next Greater Element: Array Scanning + Monotonic Stack

Primary: Stack Secondary: Array Scanning

This one is really filed under Stack as its primary category, and it's simpler than the two combos above — but it's worth a mention here because it's the cleanest, smallest example of the same underlying shape: a plain linear scan across an array, with a monotonic stack maintained alongside it to answer "what's the next bigger value" for each element in O(1) amortized instead of O(n) per query. The pattern — maintain an ordered auxiliary structure while doing a single pass — is exactly what powers the Sliding Window Maximum combo above, just without the "window" part.

Try it in the Next Greater Element visualizer, and see the full monotonic-stack mechanics on the Stack theory page.

05 · Combo #4

Huffman Coding: Greedy + Heap + Tree

Primary: Greedy Secondary: Heap Secondary: Trees

Huffman Coding stacks three ideas instead of two, and each one answers a different question:

Take any one of the three away and the algorithm breaks: without the greedy rule you don't know what to merge; without the heap the merging is too slow to be practical at scale; without building an actual tree you have no way to turn "merge order" into a usable prefix code.

Explore it in the Huffman Coding visualizer, with background on each piece in the Greedy theory page, the Heap theory page, and the Trees theory page.

06 · Method

A repeatable framework for spotting combos

  1. 1 List the problem's actual requirements separatelyFast lookup by key? Fast ordering or recency? Fast min/max over a range? A global optimum at each step? Write each one down as its own line, don't bundle them.
  2. 2 Check if one single pattern already covers everythingIf some pattern from the other theory pages satisfies every requirement on your list at once, stop there — it isn't a mixed-pattern problem, and combining structures would only add complexity for no benefit.
  3. 3 Otherwise, find which two (rarely three) patterns split the requirementsLook for one technique that covers some of your list and a second that covers the rest — the LRU Cache split is lookup vs. ordering; Sliding Window Maximum's split is windowing vs. fast max.
  4. 4 Let each structure do only what it's good atDon't force the hashmap to track order, and don't force the linked list to do key lookup. The moment you're fighting a structure to do a job it's a poor fit for, that's a sign you're missing the second piece.
  5. 5 Re-check the combined complexityO(1) plus O(1) should still be O(1) overall — verify the glue code connecting the two structures doesn't quietly introduce an O(n) scan somewhere (a linear search to "find the node," a rebuild of the heap, etc.).

07 · Before you start coding

Common mistakes