Finding MK Average

hard design heap ordered set

Problem

Design a class MKAverage built from two integers m and k. The method addElement(num) appends num to a running stream. The method calculateMKAverage() looks at the last m numbers added: if fewer than m exist it returns -1; otherwise it sorts that window, drops the smallest k and the largest k values, and returns the integer average (floor) of the remaining m − 2k numbers.

Inputm = 3, k = 1 · addElement(3), addElement(1), calculateMKAverage(), addElement(10), calculateMKAverage(), addElement(5), addElement(5), addElement(5), calculateMKAverage()
Output-1, 3, 5
After only 2 adds the window has < 3 numbers, so the query returns -1. With window {3, 1, 10}, dropping the smallest (1) and largest (10) leaves {3}, average 3. Later the last 3 are {5, 5, 5}; trimming one from each end leaves {5}, average 5.

from collections import deque

class MKAverage:
    def __init__(self, m, k):
        self.m, self.k = m, k
        self.q = deque()

    def addElement(self, num):
        self.q.append(num)
        if len(self.q) > self.m:
            self.q.popleft()

    def calculateMKAverage(self):
        if len(self.q) < self.m:
            return -1
        s = sorted(self.q)
        mid = s[self.k:self.m - self.k]
        return sum(mid) // len(mid)
class MKAverage {
  constructor(m, k) {
    this.m = m;
    this.k = k;
    this.q = [];
  }

  addElement(num) {
    this.q.push(num);
    if (this.q.length > this.m) this.q.shift();
  }

  calculateMKAverage() {
    if (this.q.length < this.m) return -1;
    const s = [...this.q].sort((a, b) => a - b);
    const mid = s.slice(this.k, this.m - this.k);
    const sum = mid.reduce((a, b) => a + b, 0);
    return Math.floor(sum / mid.length);
  }
}
class MKAverage {
    private int m, k;
    private Deque<Integer> q = new ArrayDeque<>();

    public MKAverage(int m, int k) {
        this.m = m;
        this.k = k;
    }

    public void addElement(int num) {
        q.addLast(num);
        if (q.size() > m) q.pollFirst();
    }

    public int calculateMKAverage() {
        if (q.size() < m) return -1;
        List<Integer> s = new ArrayList<>(q);
        Collections.sort(s);
        long sum = 0;
        for (int i = k; i < m - k; i++) sum += s.get(i);
        return (int)(sum / (m - 2 * k));
    }
}
class MKAverage {
    int m, k;
    deque<int> q;
public:
    MKAverage(int m, int k) : m(m), k(k) {}

    void addElement(int num) {
        q.push_back(num);
        if ((int)q.size() > m) q.pop_front();
    }

    int calculateMKAverage() {
        if ((int)q.size() < m) return -1;
        vector<int> s(q.begin(), q.end());
        sort(s.begin(), s.end());
        long sum = 0;
        for (int i = k; i < m - k; i++) sum += s[i];
        return (int)(sum / (m - 2 * k));
    }
};
Time: O(log m) per op with three ordered multisets (O(m log m) for the simple re-sort shown) Space: O(m)