Three TreeSet/ SortedList solution:
from sortedcontainers import SortedList
class MKAverage:
"""tc O(MlgM) M: size of q
"""
def __init__(self, m: int, k: int):
self.left,self.mid,self.right = SortedList([]),SortedList([]),SortedList([])
self.q = deque()
self.m_sum = 0
self.m = m
self.k = k
def addElement(self, x: int) -> None:
# alwayse insert into mid before len(q) < m
if len(self.q) < self.m:
self.mid.add(x)
self.q.append(x)
if len(self.q) == self.m:
# when len(q) == m, move items off to left and right, calculate sum
for i in range(self.k):
self.left.add(self.mid.pop(0))
for j in range(self.k):
self.right.add(self.mid.pop(-1))
# add middle sum
for val in self.mid:
self.m_sum += val
# 1. add new number nx : if we add nx to left/ right , make sure left right have exactly k numbers
# first left then right, last try mid
elif len(self.q) > self.m :
if self.left.bisect_left(x) < len(self.left):
self.left.add(x)
v1 = self.left.pop(-1)
self.mid.add(v1)
self.m_sum += v1
elif self.right.bisect_left(x) > 0:
self.right.add(x)
v2 = self.right.pop(0)
self.mid.add(v2)
self.m_sum += v2
else: # x fall into mid
self.mid.add(x)
self.m_sum += x
#2. remove oldest val in mid
rm = self.q.popleft()
# try to remove mid first, then right or left
# search
if rm in self.mid:
self.mid.remove(rm)
# update sum
self.m_sum -= rm
elif rm in self.left:
#elif self.left.bisect_left(rm) < len(self.left):
self.left.remove(rm)
else:
#print(self.left,self.mid,self.right)
self.right.remove(rm) #lg(N)
# 3. balance left and right if needed
if len(self.left) < self.k and len(self.mid)>0:
v = self.mid.pop(0)
self.left.add(v)
self.m_sum -= v
elif len(self.right) < self.k and len(self.mid)>0:
v = self.mid.pop()
self.right.add(v)
self.m_sum -= v
def calculateMKAverage(self) -> int:
if len(self.q) == self.m:
return self.m_sum//(self.m-2*self.k)
return -1
# Your MKAverage object will be instantiated and called as such:
# obj = MKAverage(m, k)
# obj.addElement(num)
# param_2 = obj.calculateMKAverage()
TODO: BIT version