/**
* 362. Design Hit Counter
* Design a hit counter which counts the number of hits received in the past 5 minutes.
* Each function accepts a timestamp parameter (in seconds granularity) and you may assume that calls are
* being made to the system in chronological order (ie, the timestamp is monotonically increasing).
* You may assume that the earliest timestamp starts at 1.
* It is possible that several hits arrive roughly at the same time.
* Example:
* HitCounter counter = new HitCounter();
* // hit at timestamp 1.
* counter.hit(1);
* // hit at timestamp 2.
* counter.hit(2);
* // hit at timestamp 3.
* counter.hit(3);
* // get hits at timestamp 4, should return 3.
* counter.getHits(4);
* // hit at timestamp 300.
* counter.hit(300);
* // get hits at timestamp 300, should return 4.
* counter.getHits(300);
* // get hits at timestamp 301, should return 3.
* counter.getHits(301);
* Follow up:
* What if the number of hits per second could be very large? Does your design scale?
*/
See the solution to the problem on github here: https://github.com/zcoderz/leetcode/blob/main/src/main/java/frequent/medium/HitCounter.java
Solution is simple:
- Keep the count of times in a treemap
- For insertions, add the data to time stamp and increment count
- For retrieval
- Use headMap to get values less than and inclusive of the time stamp
- Use tailMap to filter out values less than the prior (timestamp – 5*60) threshold
- Iterate over data to calculate total count while skipping the row with key equal to prior
Here is the code:
/** Record a hit.
@param timestamp - The current timestamp (in seconds granularity). */
void hit(int timestamp) {
int count = set.getOrDefault(timestamp, 0);
set.put(timestamp, count+1);
}
/** Return the number of hits in the past 5 minutes.
@param timestamp - The current timestamp (in seconds granularity). */
public int getHits(int timestamp) {
int prior = timestamp - (60*5);
//search the lower and higher edges to find the count.
SortedMap<Integer, Integer> less = set.headMap(timestamp, true);
SortedMap<Integer, Integer> tailMap = less.tailMap(prior);
int count = 0;
for (Map.Entry<Integer, Integer> entry : tailMap.entrySet()) {
//strip out any record equal to prior value as that maybe present but shouldn't to be included
if (entry.getKey().equals(prior)) continue;
count += entry.getValue();
}
return count;
}