Skip to content
AI360Xpert
Beta

Design Hit Counter

Problem in Plain English

Count how many hits landed in the trailing 300-second window ending at a query timestamp. Hits arrive in chronological order and several may share one timestamp.

Problem Statement

Design a hit counter that records hits and reports how many arrived in the past 5 minutes, meaning timestamps t with timestamp - t < 300.

The hit operation records one hit at a timestamp, and getHits returns the count of recorded hits inside the window ending at its timestamp. Calls arrive in chronological order, and several hits may share the same timestamp.

Constraints

  • 1<=timestamp<=2∗1091 <= timestamp <= 2 * 10^9
  • Timestamps arrive in non-decreasing chronological order.
  • A hit at t counts for queries with timestamp - t < 300.
  • At most 300 calls are made to hit and getHits.

Examples

Example 1

Input
["HitCounter", "hit", "hit", "hit", "getHits", "hit", "getHits", "getHits"] [[], [1], [2], [3], [4], [300], [300], [301]]
Output
[null, null, null, null, 3, null, 4, 3]

Hits at 1, 2, and 3 are all live at 4. After hit(300) the count at 300 is 4, and at 301 the hit from 1 expires, leaving 3.

Example 2

Input
["HitCounter", "hit", "getHits", "getHits"] [[], [1], [4], [301]]
Output
[null, null, 1, 0]

The hit at 1 is inside the window at 4 since 4 - 1 < 300, but expired by 301 since 301 - 1 is not below 300.

Example 3

Input
["HitCounter", "getHits", "hit", "hit", "getHits", "hit", "getHits", "getHits"] [[], [1], [1], [1], [300], [301], [301], [601]]
Output
[null, 0, null, null, 2, null, 1, 0]

An empty counter returns 0. Two hits at second 1 still count at second 300, age 299. At 301 they both expire exactly at age 300; the new hit at 301 replaces their modulo bucket and counts once. At 601 that hit also expires.

Intuition

At query time 301, the five-minute window contains seconds 2 through 301: the hit at 1 has just expired, while hits at 2, 3 and 300 remain. Chronological calls let a queue discard expired hits from its front. A stronger observation is that the window contains only 300 distinct integer seconds, so 300 stamped buckets can combine all hits sharing a second without confusing a reused bucket with its previous timestamp.

Approaches

Hit Queue

Solution Details

Reveal Hit Queue: intuition, complexity, and code

Hints

Hint 1
Because timestamps never go backward, the oldest stored hit is always at the front of a queue.
Hint 2
Storing every hit separately wastes space when thousands share one timestamp, so group hits by their second.
Hint 3
Map each timestamp to one of 300 buckets with timestamp % 300, and stamp each bucket so a collision with an old window is detected instead of double counted.

Edge Cases

  • No hits yet: zero counts make getHits return 0, even when unused stamp 0 is younger than 300.
  • A hit at t counts at t + 299 but expires exactly at t + 300.
  • Repeated hits at the same second must all count; equal query timestamps leave the answer unchanged until another hit.
  • Modulo collisions such as 1 and 301 reset the bucket, while a gap of several full windows makes every old stamp stale.
  • Timestamps near 2000000000 remain safe for Java int subtraction under the positive timestamp constraint.

Common Mistakes and Interview Tips

  • Evicting with timestamp - front > 300 instead of >= 300, which keeps a hit that is exactly 300 old.
  • Reusing a collided bucket without comparing stamps, which mixes the old window count into the new one.
  • Resetting the count on every hit instead of only when the stamp differs, which erases same-second bursts.
  • Assuming the queue uses only 300 entries: arbitrarily many hits may share one second, and the JavaScript head-index version also retains expired slots.
  • Interview tip: distinguish O(n) worst-case queue query time from amortized constant work, then prove why modulo collisions cannot discard any live hit.

Key Takeaway

A fixed window over ordered time folds into a circular buffer: modulo indexing bounds the memory while stored stamps separate the current window from ghosts.