LC 0346 [E] Moving Average from Data Stream - ALawliet/algorithms GitHub Wiki
sliding window (deque with max size)
class MovingAverage(object):
def __init__(self, size):
self.dq = deque()
self.maxlen = size
self.total = 0
def next(self, val):
self.dq.append(val)
if len(self.dq) > self.maxlen:
self.total -= self.q.popleft()
self.total += val
return self.total / len(self.dq)
class MovingAverage(object):
def __init__(self, size):
self.dq = deque(maxlen=size) # maxlen will popleft() for us
def next(self, val):
self.dq.append(val)
return sum(self.dq) / len(self.dq)
class MovingAverage:
def __init__(self, size: int):
self.size = size
self.queue = deque()
# number of elements seen so far
self.window_sum = 0
self.count = 0
def next(self, val: int) -> float:
# calculate the new sum by shifting the window
self.queue.append(val)
tail = self.queue.popleft() if len(self.queue) > self.size else 0
self.window_sum = self.window_sum - tail + val
return self.window_sum / len(self.queue)
class MovingAverage:
def __init__(self, size: int):
self.size = size
self.queue = [0] * self.size
self.head = self.window_sum = 0
# number of elements seen so far
self.count = 0
def next(self, val: int) -> float:
self.count += 1 # we need to track count because len(queue) is always size now
# calculate the new sum by shifting the window
tail = (self.head + 1) % self.size
self.window_sum = self.window_sum - self.queue[tail] + val
# move on to the next head
self.head = (self.head + 1) % self.size
self.queue[self.head] = val
n = min(self.size, self.count) # n will either be the max size or not there yet
print(self.size, self.count, n)
return self.window_sum / n
class MyCircularQueue:
def __init__(self, k: int):
self.q = [0] * k
self.headIndex = 0
self.n = 0
self.k = self.capacity = k
def enQueue(self, value: int) -> bool:
if self.n == self.k:
self.deQueue()
nextHeadIndex = (self.headIndex + self.n) % self.k
self.q[nextHeadIndex] = value # set the value at next available spot
self.n += 1
return True
def deQueue(self) -> bool:
nextHeadIndex = (self.headIndex + 1) % self.k
self.headIndex = nextHeadIndex # just move the head forward
self.n -= 1
return True
def Front(self) -> int: # where is the current head?
if not self.n:
return -1
return self.q[self.headIndex]
def Rear(self) -> int: # where is the current tail?
if not self.n:
return -1
tailIndex = (self.headIndex + self.n - 1) % self.k
return self.q[tailIndex]
def isEmpty(self) -> bool:
return not self.n
def isFull(self) -> bool:
return self.n == self.k
class MovingAverage:
def __init__(self, size: int):
self.queue = MyCircularQueue(size)
def next(self, val: int) -> float:
self.queue.enQueue(val)
return sum(self.queue.q) / self.queue.n
don't be dumb:
from collections import deque
size = 3
items = [1,2,3,4,5]
q = deque()
for i in items:
runsum = q[-1] + i if q else i
if len(q) + 1 > size:
minus = q.popleft()
print('popleft', runsum, minus)
runsum -= minus # this is wrong because we decremented the old running sum
q.append(runsum)
print(q, runsum)
print('***')
q = deque()
cumsum = 0
for i in items:
cumsum += i
if len(q) == size:
minus = q.popleft()
print('popleft', cumsum, minus)
cumsum -= minus # this is correct because we decremented the old value
q.append(i)
print(q, cumsum)
deque([1]) 1
deque([1, 3]) 3
deque([1, 3, 6]) 6
popleft 10 1
deque([3, 6, 9]) 9
popleft 14 3
deque([6, 9, 11]) 11
***
deque([1]) 1
deque([1, 2]) 3
deque([1, 2, 3]) 6
popleft 10 1
deque([2, 3, 4]) 9
popleft 14 2
deque([3, 4, 5]) 12