Design Hit Counter - Problem
Design a Hit Counter System
Imagine you're building a real-time analytics system that needs to track website hits or API requests. You need to design a HitCounter class that efficiently counts the number of hits received in the past 5 minutes (300 seconds).
Your system will receive timestamps in chronological order and needs to support two operations:
โข
โข
Key Challenge: Multiple hits can occur at the same timestamp, and you need to efficiently handle the sliding window of 300 seconds while maintaining good performance for both operations.
Example:
Imagine you're building a real-time analytics system that needs to track website hits or API requests. You need to design a HitCounter class that efficiently counts the number of hits received in the past 5 minutes (300 seconds).
Your system will receive timestamps in chronological order and needs to support two operations:
โข
hit(timestamp) - Record a hit at the given timestampโข
getHits(timestamp) - Return the count of hits in the past 300 seconds from the given timestampKey Challenge: Multiple hits can occur at the same timestamp, and you need to efficiently handle the sliding window of 300 seconds while maintaining good performance for both operations.
Example:
HitCounter counter = new HitCounter();counter.hit(1); // hit at timestamp 1counter.hit(2); // hit at timestamp 2counter.hit(3); // hit at timestamp 3counter.getHits(4); // returns 3 (hits at 1,2,3 are within [4-300, 4])counter.hit(300); // hit at timestamp 300counter.getHits(300); // returns 4 (all hits within [1, 300])counter.getHits(301); // returns 1 (only hit at 300 within [2, 301]) Input & Output
basic_operations.py โ Basic Hit Counter Usage
$
Input:
HitCounter counter = new HitCounter();
counter.hit(1);
counter.hit(2);
counter.hit(3);
counter.getHits(4); // query at timestamp 4
counter.hit(300);
counter.getHits(300); // query at timestamp 300
counter.getHits(301); // query at timestamp 301
โบ
Output:
null
null
null
null
3
null
4
1
๐ก Note:
At timestamp 4, all hits (1,2,3) are within [4-300+1, 4] = [-295, 4]. At timestamp 300, all hits (1,2,3,300) are within [1, 300]. At timestamp 301, only hit at 300 is within [2, 301].
multiple_hits_same_timestamp.py โ Multiple Hits
$
Input:
HitCounter counter = new HitCounter();
counter.hit(1);
counter.hit(1);
counter.hit(1);
counter.hit(2);
counter.getHits(2);
โบ
Output:
null
null
null
null
4
๐ก Note:
Multiple hits can occur at the same timestamp. At timestamp 2, we have 3 hits at timestamp 1 and 1 hit at timestamp 2, totaling 4 hits within the window.
sliding_window_edge_case.py โ Sliding Window
$
Input:
HitCounter counter = new HitCounter();
counter.hit(100);
counter.hit(200);
counter.hit(300);
counter.getHits(300);
counter.getHits(399);
counter.getHits(400);
โบ
Output:
null
null
null
3
3
2
๐ก Note:
At 300: hits 100,200,300 are within [1,300]. At 399: hits 100,200,300 are within [100,399]. At 400: only hits 200,300 are within [101,400], so count is 2.
Visualization
Tap to expand
Understanding the Visualization
1
Hit Recording
When a hit occurs at timestamp T, map it to bucket T % 300 in the circular array
2
Bucket Management
If the bucket is outdated (timestamp differs), reset it and store the new hit count
3
Query Processing
For getHits(T), scan all 300 buckets and sum counts from buckets with timestamps > T-300
4
Sliding Window
The circular array naturally maintains a 300-second sliding window, automatically aging out old data
Key Takeaway
๐ฏ Key Insight: The circular array approach transforms the sliding window problem into a fixed-size array problem, achieving optimal O(1) time and space complexity while naturally handling the time-based expiration of old data.
Time & Space Complexity
Time Complexity
O(1) amortized
hit() is O(1), getHits() scans at most 300 buckets which is O(1) constant
โ Linear Growth
Space Complexity
O(1)
Fixed space of 300 buckets regardless of number of hits
โ Linear Space
Constraints
- 1 โค timestamp โค 2 ร 109
- All the calls are being made to the system in chronological order (i.e., timestamp is monotonically increasing)
- At most 300 calls will be made to hit and getHits
- Follow up: What if the number of hits per second could be huge? Does your design scale?
๐ก
Explanation
AI Ready
๐ก Suggestion
Tab
to accept
Esc
to dismiss
// Output will appear here after running code