Sliding Window Rate Limiter
Reported by candidates from Mercury's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.
The mistake that sinks a first attempt on Mercury's Sliding Window Rate Limiter is counting rejected requests against the limit. Mercury candidates reported this OA in September 2026, and it looks easy until the edge cases bite. You get payment-transfer requests in timestamp order, each tagged with an organization ID, and you return 1 or 0 for each. It's a per-organization sliding window with a queue. If you blank on the expiry boundary during the live assessment, StealthCoder runs invisibly as a safety net and hands you the clean version.
The problem
You receive payment-transfer API requests in nondecreasing timestamp order. Each request has an organization identifier. For each request at time t, allow it when fewer than limit previously allowed requests for the same organization have timestamps strictly greater than t - windowSize. A previously allowed request exactly windowSize milliseconds old has expired. Rejected requests do not consume capacity. Return an array with 1 for every allowed request and 0 for every rejected request, preserving input order. Function allowedRequests(organizationIds: int[], timestamps: int[], limit: int, windowSize: int) → int[] Examples Example 1 organizationIds = [1,1,1,1] timestamps = [0,2,5,10] limit = 2 windowSize = 10 return = [1,1,0,1] The requests at times 0 and 2 fill the window. The request at 5 is rejected. At time 10, the accepted request at time 0 has expired, so the request is allowed. Example 2 organizationIds = [7,8,7,8,7] timestamps = [1,1,2,3,4] limit = 1 windowSize = 3 return = [1,1,0,0,1] Each organization has an independent window. The second request for each organization is rejected. At time 4, organization 7 may proceed because its accepted request at time 1 is exactly one window old. Example 3 organizationIds = [3,3,3,3] timestamps = [5,5,5,5] limit = 3 windowSize = 100 return = [1,1,1,0] Equal timestamps are processed in input order. The first three requests are accepted and the fourth is rejected. Constraints 1 ≤ organizationIds.length = timestamps.length ≤ 2 * 10^5. 1 ≤ organizationIds[i] ≤ 10^9. 0 ≤ timestamps[i] ≤ 10^9, and timestamps is nondecreasing. 1 ≤ limit ≤ 10^5. 1 ≤ windowSize ≤ 10^9.
Reported by candidates. Source: FastPrep
Pattern and pitfall
Keep a hash map from organization ID to a deque of accepted timestamps. For each request at time t, pop from the front while the oldest timestamp is less than or equal to t - windowSize. That's the exact-boundary rule: a request exactly windowSize old is expired. Then if the deque size is below limit, push t and output 1. Otherwise output 0 and push nothing. The common pitfall is using strictly less than when evicting, which keeps the boundary request alive and breaks Example 2. The second pitfall is recording rejected requests, which makes the window never recover. Timestamps are nondecreasing, so each deque stays sorted and eviction only touches the front. Every request is pushed and popped at most once, so the total work is O(n). With n up to 2 * 10^5, anything that rescans the window per request will be too slow. StealthCoder is your hedge if the boundary logic slips under pressure.
StealthCoder is the hedge for the one pattern you didn't drill. It runs invisibly during the screen share.
You can drill Sliding Window Rate Limiter 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. If you're reading this with an OA window open, you're who this was built for.
Get StealthCoderRelated leaked OAs
This OA pattern shows up on LeetCode as design hit counter. If you have time before the OA, drill that.
You've seen the question.
Make sure you actually pass Mercury's OA.
Mercury reuses patterns across OAs. If you're reading this with an OA window open, you're who this was built for. Works on HackerRank, CodeSignal, CoderPad, and Karat.
Sliding Window Rate Limiter FAQ
What's the trick in Mercury's Sliding Window Rate Limiter?+
Track accepted timestamps only, per organization, in a deque. Evict from the front while the oldest is at or below t - windowSize, then accept if the size is under the limit. Rejected requests never get stored. That's the whole problem once the boundary is right.
How do I handle the expiry boundary?+
A request exactly windowSize old is expired, so evict when oldest <= t - windowSize. Example 2 tests this: organization 7 at time 4 with window 3 must be allowed because its request at time 1 is exactly one window old.
What data structure should I use?+
A hash map keyed by organization ID, with a queue or deque of accepted timestamps as the value. Since timestamps arrive nondecreasing, each queue stays sorted. In Python use collections.deque, and in Java use ArrayDeque inside a HashMap.
What's the time complexity, and does it matter here?+
O(n) total, because each accepted timestamp is added once and removed at most once. It matters with n up to 2 * 10^5. Rescanning the whole window for each request can degrade badly when limit is large, so don't do it.
How do I prepare for this in 48 hours?+
Write the deque solution from scratch once, then test the three given examples by hand, especially equal timestamps and the exact-expiry case. Also think through what happens with many distinct organization IDs. That covers nearly every way this problem can go wrong.