# 362 Design Hit Counter

設計一個計算點擊的程式。

包含兩個函式:getHits()可取得某timestamp五分鐘之內的總hit數量,hit()表示在某時間點有人點擊,要加入記錄。

此題有兩種存法:

  1. Queue: 另創一個class叫Record,成員有timestamp和點擊次數,精確度可以無限大。
  2. Arrays: 一個array存timestamp,另一個存點擊次數。時間複雜度比較低。

Queue

宣告一個Queue<Record>來記錄所有timestamp的點擊次數,

還有一個int curHit記錄整個queue裡面的total hit.

  • hit(): 每次點擊,就先把queue中不是五分鐘之內的記錄poll出來,再檢查此timestamp是否已經在queue中,若是,直接把該記錄的hitCount++,若否,加入一個新紀錄。
  • getHits(): 用queue.peek()檢查queue中有沒有不是五分鐘之內的記錄,如果有,要把它們poll出來,並且從curHit中減掉。
/***
use a queue to save all record
for infinite granularity
***/


public class HitCounter {

    public class Record{
    int time;
    int hitCount;
        public Record(int t, int c){
            this.time = t;
            this.hitCount = c;
        }
    }

    Queue<Record> queue;
    int curHit;
    /** Initialize your data structure here. */
    public HitCounter() {
        queue = new LinkedList<Record>();
        curHit = 0;
    }

    /** Record a hit.
        @param timestamp - The current timestamp (in seconds granularity). */
    public void hit(int timestamp) {
        //remove all the element which is not within 5 mins
        //if queue is not empty && timestamp == queue.peek().time
        //      queue.peek().hitCount += 1;
        //else 
        //  if timestamp - queue.peek().time >=300
        //      queue.poll();
        //  queue.add(new Record(timestamp, 1))
        //curHit++;
        while(!queue.isEmpty() && queue.peek().time <= timestamp - 300) {
            curHit -= queue.poll().hitCount;
        }
        if(!queue.isEmpty() && timestamp == queue.peek().time)
            queue.peek().hitCount += 1;
        else{
            queue.add(new Record(timestamp, 1));
        }
        curHit++;
    }

    /** Return the number of hits in the past 5 minutes.
        @param timestamp - The current timestamp (in seconds granularity). */
    public int getHits(int timestamp) {
        //while the queue is not empty, and the first element in the queue is not within 5 min
        //  take it out from current hit count and poll the element
        while(!queue.isEmpty() && queue.peek().time <= timestamp - 300) {
            curHit -= queue.poll().hitCount;
        }
        return curHit;
    }
}

/**
 * Your HitCounter object will be instantiated and called as such:
 * HitCounter obj = new HitCounter();
 * obj.hit(timestamp);
 * int param_2 = obj.getHits(timestamp);
 */

Array

宣告兩個array,一個存timestamp,另一個存hit,time[i]的點擊次數即為hit[i]。

  • hit(): the index of time array is timestamp % 300. Why? for example, when timestamp = 301, the hit at timestamp = 1 is not within 5 min anymore, should be discarded. 如果timestamp == time[index],hit[index]++,否則就要更新time[index],hit[index]從1開始累計。
  • getHits(): for each element in time array, 如果time[i]是在timestamp的五分鐘之內,即把hit[i]加到total裡面。
/***
use 2 arrays to save time and hit
***/
public class HitCounter {
    //create an array of size 300 to save "time"
    //create an array of size 300 to save "hit"
    int[] time;
    int[] hit;

    /** Initialize your data structure here. */
    public HitCounter() {
        //initialize the size of time and hitCount array
        time = new int[300];
        hit = new int[300];
    }

    /** Record a hit.
        @param timestamp - The current timestamp (in seconds granularity). */
    public void hit(int timestamp) {
        //int index = timestamp % 300, 
        //for example, when timestamp= 301, 
        //the hit at timestamp = 1 is not in 5 min, should be discarded.

        //if timestamp equals to time[index], we should keep incrementing hit[index]
        //else start hit[index] from 1, update time[index]=timestamp
        int index = timestamp % 300;
        if(timestamp == time[index]){
            hit[index]++;
        }
        else{
            //if having multiple thread, need a lock()
            hit[index] = 1;
            time[index] = timestamp;
        }

    }

    /** Return the number of hits in the past 5 minutes.
        @param timestamp - The current timestamp (in seconds granularity). */
    public int getHits(int timestamp) {
        //int total to save the answer
        //for each element in hit[]
        //  if timestamp - time[i] < 300, add hit[i] to total
        int total = 0;
        for(int i=0; i<300; i++){
            if(timestamp - time[i] < 300){
                total += hit[i];
            }
        }
        return total;
    }
}

/**
 * Your HitCounter object will be instantiated and called as such:
 * HitCounter obj = new HitCounter();
 * obj.hit(timestamp);
 * int param_2 = obj.getHits(timestamp);
 */

results matching ""

    No results matching ""