LRU Cache with Hit and Miss Counters
Reported by candidates from LinkedIn's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.
The detail that trips people in this LinkedIn OA, reported September 2026, is the last line: STATS with a rate rounded half up to exactly three decimals. The cache part is a standard LRU, but the output format is where points leak. You track hits and misses on every GET, update recency on every PUT and every successful GET, and evict the oldest key when you go over capacity. It's a design problem with a hash map and an ordering structure. If you blank on the linked list wiring mid-assessment, StealthCoder runs invisibly as a safety net, so you aren't stuck staring at a pointer bug.
The problem
Simulate a least-recently-used cache of string keys and values. Process commands PUT key value and GET key. A successful GET returns HIT value and makes that key most recently used; a missing GET returns MISS. Updating a key also makes it most recently used. An insertion beyond capacity evicts the least recently used key. After all commands, append STATS hits misses rate, where rate is hits divided by all GET operations and rounded to exactly three decimal places using round half up: an exact halfway value rounds upward. Return 0.000 when there were no GET operations. Function runLruWithCounters(capacity: int, operations: String[]) → String[] Examples Example 1 capacity = 2 operations = ["PUT a 10","PUT b 20","GET a","PUT c 30","GET b","GET c"] return = ["HIT 10","MISS","HIT 30","STATS 2 1 0.667"] Reading a makes b least recently used, so inserting c evicts b. Example 2 capacity = 1 operations = ["PUT x old","PUT x new","GET x"] return = ["HIT new","STATS 1 0 1.000"] Updating x replaces its value without creating a second entry. Constraints 1 <= capacity <= 100000 0 <= operations.length <= 200000 Each command is exactly PUT key value or GET key. Keys and values are nonempty ASCII tokens without whitespace.
Reported by candidates. Source: FastPrep
Pattern and pitfall
The trick is O(1) for every operation. Pair a hash map with a doubly linked list, or use an ordered map that supports move-to-end. GET hit: move the node to most recent, count a hit. GET miss: count a miss, output MISS. PUT on an existing key: replace the value and move it to most recent, no eviction. PUT on a new key: insert, then evict the least recent if size exceeds capacity. The common pitfalls are treating an update as a new insertion, forgetting that a hit refreshes recency, and botching the rate. Don't trust default float formatting. Compute with integers: rounded = (hits * 1000 * 2 + total) / (2 * total), integer division, then pad to three decimals. Handle total = 0 by returning 0.000. With 200000 operations, a list scan for recency will time out. If the pointer logic slips under pressure, StealthCoder is the hedge on the live OA.
If you see this problem in your OA tomorrow, the play is to recognize the pattern in 30 seconds. StealthCoder buys you that recognition.
You can drill LRU Cache with Hit and Miss Counters cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. Built by an Amazon engineer who passed his OA cold and still thinks the filter is broken.
Get StealthCoderRelated leaked OAs
This OA pattern shows up on LeetCode as lru cache. If you have time before the OA, drill that.
You've seen the question.
Make sure you actually pass LinkedIn's OA.
LinkedIn reuses patterns across OAs. Built by an Amazon engineer who passed his OA cold and still thinks the filter is broken. Works on HackerRank, CodeSignal, CoderPad, and Karat.
LRU Cache with Hit and Miss Counters FAQ
What's the trick in the LinkedIn LRU cache with counters problem?+
Use a hash map plus a doubly linked list, or an ordered dictionary, so every PUT and GET is O(1). The extra twist is the STATS line, which needs correct hit and miss counts and exact half-up rounding to three decimals.
How do I round half up to three decimals safely?+
Skip floating point. With integers, compute (2000 * hits + total) / (2 * total) using integer division. That gives the rate times 1000, rounded half up. Then format it as whole part, a dot, and three padded digits. If total is 0, output 0.000.
Does a PUT on an existing key evict anything?+
No. Updating a key replaces its value and moves it to most recently used. Size stays the same, so no eviction happens. Eviction only fires when inserting a brand new key pushes the size past capacity, as Example 2 shows.
Do misses change recency or the cache contents?+
No. A GET miss only increments the miss counter and outputs MISS. It doesn't insert anything and doesn't touch ordering. Only successful GETs and PUTs refresh recency.
How do I prepare for this in 48 hours?+
Write an LRU cache from scratch twice, once with a custom linked list and once with your language's ordered map. Then add the counters and the rounding helper. Test capacity 1, repeated updates, and zero GETs. That covers nearly every edge case here.