Design Hit Counter
Problem (restated)
Record hits at integer timestamps (seconds). getHits(t) returns hits in the past 300 seconds inclusive of t (i.e. (t-300, t]).
Intuition
Queue of hit times; on getHits drop timestamps ≤ t-300.
Approaches
Queue of timestamps (300s)
UnverifiedIdea. hit enqueues; getHits while front ≤ t-300 dequeue; return size.
Walkthrough. hit 1,2,3; getHits(4)=3; hit 300; getHits(300)=4; getHits(301)=3.
Trade-offs. Bucket arrays of size 300 scale better under high QPS with many hits/sec.
export class HitCounter {
private q: number[] = [];
hit(timestamp: number): void {
this.q.push(timestamp);
}
getHits(timestamp: number): number {
while (this.q.length && this.q[0]! <= timestamp - 300) this.q.shift();
return this.q.length;
}
}
export class HitCounter {
private q: number[] = [];
hit(timestamp: number): void {
this.q.push(timestamp);
}
getHits(timestamp: number): number {
while (this.q.length && this.q[0]! <= timestamp - 300) this.q.shift();
return this.q.length;
}
}
Template connection
Queue of recent events (same family as RecentCounter).
Reflection
getHitsdrops timestamps older than 300 seconds from the front. The window is(t - 300, t].- Several hits share a timestamp. One record each, or a counter? What does that change about memory?
- Time does not go backward. Without that guarantee a queue is not enough.