Moving Stream Average

moving avg,就是一个stream输入,给一个int getNow()API获取当前timestamp, 完成两个函数void record(int value)和double getAvg(),有输入时会自动call record, 然后call getAvg()时返回5分钟内的平均值。用一个queue来存数据,一个sum存当前和, 每次record和getAvg时pop掉过期的数据就好了。

import java.util.LinkedList;
import java.util.Queue;


public class Movingaverage {
    class Event{
        int time;
        int val;

        public Event(int time, int val){
            this.time = time;
            this.val = val;
        }

    }

    Queue<Event> queue = new LinkedList<Event>();
    int sum;
    public int getNow(){
        return 1;
    }

    public void record(int val){
        Event event = new Event(getNow(), val);
        queue.offer(event);
        removeExpireRecord();
    }

    public double getAvg(){
        removeExpireRecord();
        if(queue.isEmpty()) return 0;
        return (double) sum / queue.size();
    }

    public void removeExpireRecord(){
        while(! queue.isEmpty() && Math.abs(queue.peek().time - getNow()) > 5){
            Event cur = queue.poll();
            sum -= cur.val;
        }
    }

}

follow up: 如果还要getMedium呢?我说用two heap, 他说太慢了因为record要o(logN),说这个getMedium call得很少,可以直接在当前的数据结构上implement, 于是其实就是求unsorted list的medium,用quick select能O(n)时间得到,面试官表示很满意。

    public double Medium(){
        int[] res = new int[queue.size()];
        for(int i = 0; i < res.length; i++){
            res[i] = ((LinkedList<Event>) queue).get(i).val;
        }
        if(res.length % 2 == 0){
            int left = getMedium(res, 0, res.length - 1,  res.length / 2 - 1);
            int right = getMedium(res,0, res.length - 1, res.length / 2 );
            return (left + right) / 2;

        }else{
            int left = getMedium(res, 0, res.length - 1,res.length / 2 );
            return left ;
        }

    }
    public static int getMedium(int[] res, int l, int r,int k){
        if(l == r) return res[l];
        int position = getPartation(res,l,r,k);
        if(position == k){
            return res[k];
        }else if(position < k){
            return getMedium(res, position + 1, r, k);
        }else{
            return getMedium(res, l, position - 1, k);
        }
    }

    public static int getPartation(int[] res, int left, int right, int k){

        int pivot = res[right];
        for(int i = left; i < right; i++){
            if(res[i] <= pivot){
                swap(res, left, i);
                left++;
            }
        }
        swap(res, left, right);
        return left;
    }

    public static void swap(int[]res, int i, int j){
        int temp = res[i];
        res[i] = res[j];
        res[j] = temp;
    }

results matching ""

    No results matching ""