Circular buckets
Time O(1) hit, O(300) getHits Space O(300)times[i] and counts[i] for i = t % 300. On hit, reset the bucket if it holds an old second. getHits sums buckets whose time is within the window.
hit(1), hit(2), hit(3), getHits(4), hit(300), getHits(300), getHits(301)times(map)
Step 1/5hit(1), hit(2), hit(3): slot = timestamp % 300. Each slot gets its timestamp and a count of 1. Cells show counts; the other 296 slots are all 0.
class HitCounter {
private final int[] times = new int[300], counts = new int[300];
public HitCounter() {}
public void hit(int timestamp) {
int i = timestamp % 300;
if (times[i] != timestamp) { times[i] = timestamp; counts[i] = 0; }
counts[i]++;
}
public int getHits(int timestamp) {
int total = 0;
for (int i = 0; i < 300; i++) if (timestamp - times[i] < 300) total += counts[i];
return total;
}
}Verdict: Memory is constant even with millions of hits per second.