題目
Write a class RecentCounter to count recent requests.
It has only one method: ping(int t), where t represents some time in milliseconds.
Return the number of pings that have been made from 3000 milliseconds ago until now.
Any ping with time in [t - 3000, t] will count, including the current ping.
It is guaranteed that every call to ping uses a strictly larger value of t than before.
Example 1:
Input: inputs = [“RecentCounter”,“ping”,“ping”,“ping”,“ping”], inputs = [[],[1],[100],[3001],[3002]]
Output: [null,1,2,3,3]
Note:
Each test case will have at most 10000 calls to ping.
Each test case will call ping with strictly increasing values of t.
Each call to ping will have 1 <= t <= 10^9.
分析
題意:傳入毫秒數t的數組(那個inputs=[“RecnetCounter”]我沒搞明白是幹啥的)。t表示的是:當前進行ping請求時的時刻。
查詢每個最近3000ms內的請求個數(如果當前3000ms已過,則重新計數)。
inputs = [[],[1],[100],[3001],[3002]]意思是,在1ms,100ms,3001ms和3002ms各發送了一個請求。
從第一個正式請求:1ms開始計時,3000ms內也就是3000+1ms,因此3000ms內的請求包括[],[1],[100],[3001]
所以算法就是:固定第一個時刻t0,然後如果後面進來的ping請求時刻在t0+3000內,那就讓請求數目+1.如果時刻已經累計了3000ms,那麼將當前時刻作爲第一個時刻,重複操作。
由於整個請求過程是類,因此我們需要用集合存儲。
由於我們需要隨時跟第一個時刻進行對比,因此需要選擇隨時獲取第一個元素的集合。
由於存在周而復始的出和入,顯然,我們可以使用隊列。
舉例:
[[],[642],[1849],[4921],[5936],[5957]]
642爲初始時刻,size=1
1849<=642+3000,因此此時size=2
4921>642+3000,因此此時size重置爲1
5936<=4921+3000,此時size2
5957<=4921+3000,此時size=3
答案爲[1,2,1,2,3]
解答
前置知識:Java的隊列
offer,add 區別:
一些隊列有大小限制,因此如果想在一個滿的隊列中加入一個新項,多出的項就會被拒絕。
這時新的 offer 方法就可以起作用了。它不是對調用 add() 方法拋出一個 unchecked 異常,而只是得到由 offer() 返回的 false。
poll,remove 區別:
remove() 和 poll() 方法都是從隊列中刪除第一個元素。remove() 的行爲與 Collection 接口的版本相似, 但是新的 poll() 方法在用空集合調用時不是拋出異常,只是返回 null。因此新的方法更適合容易出現異常條件的情況。
peek,element區別:
element() 和 peek() 用於在隊列的頭部查詢元素。與 remove() 方法類似,在隊列爲空時, element() 拋出一個異常,而 peek() 返回 null。
官方答案
class RecentCounter {
Queue<Integer> q;
public RecentCounter() {
q = new LinkedList();
}
public int ping(int t) {
q.add(t);
while (q.peek() < t - 3000)
q.poll();
return q.size();
}
}