Sponsored
Sponsored
One natural approach to solve this problem is to use a queue data structure. A queue is perfect for this task because it works on a first-in-first-out (FIFO) principle. When a new request arrives, we add it to the queue. We also remove requests from the front of the queue that are older than 3000 milliseconds compared to the current time t
. This allows us to keep only the requests within the last 3000 milliseconds in the queue. The number of such requests is simply the size of the queue after cleaning.
Time Complexity: Amortized O(1) because each request can only be removed once from the queue.
Space Complexity: O(W), where W is the maximum number of recent requests within 3000 milliseconds.
1class RecentCounter {
2 constructor() {
3 this.queue = [];
4 }
5
6 ping(t) {
7 this.queue.push(t);
8 while (this.queue[0] < t - 3000) {
9 this.queue.shift();
10 }
11 return this.queue.length;
12 }
13}
The JavaScript implementation uses an array to simulate a queue. We add new pings to the array and remove old ones by shifting the array. The length of the array gives the count of current valid requests.
An alternative approach to using a queue is to use a double-ended queue (deque). While similar to a queue, a deque allows us to add and remove elements from both ends, but in this problem, we'll only need the standard queue operations.
The logic remains the same: insert new request times to the back of the deque and remove outdated ones from the front. This keeps the deque maintaining only the relevant requests within the [t-3000, t] range.
Time Complexity: Amortized O(1) for each ping
due to efficient pop and push operations.
Space Complexity: O(W), where W is size of the time window.
1class RecentCounter {
2
The JavaScript implementation uses an array as a deque, performing append and pop operations to maintain the window of timestamps within valid range.