346. Moving Average from Data Stream
On LeetCode ->Problem¶
Maintain a stream of integers. After each insertion, return the average of the last size values, or all values so far if fewer have arrived.
size = 3
next(val) window result
next(1) [1] 1.0
next(10) [1, 10] 5.5
next(3) [1, 10, 3] 4.66667
next(5) [10, 3, 5] 6.0
Key trick¶
Keep a FIFO queue and a running sum; subtract the oldest value when the window exceeds its capacity.
Trap¶
- Divide by the current window length, not always by
size. - Avoid recomputing the sum or using
list.pop(0): both take \(O(\text{size})\) per call. - A bounded deque silently discards values, so capture the outgoing value before updating the sum.
Why is it interesting?¶
It turns repeated aggregation into constant-time updates by retaining only the state needed for the next answer.
Python solution¶
from collections import deque
class MovingAverage:
def __init__(self, size: int):
self.size = size
self.q = deque()
self.total = 0
def next(self, val: int) -> float:
self.q.append(val)
self.total += val
if len(self.q) > self.size:
self.total -= self.q.popleft()
return self.total / len(self.q)
Time: \(O(1)\) per next call.
Space: \(O(\text{size})\).
Comment on my solution¶
Your solution is correct and interview-ready: it uses a running sum, evicts the oldest value, and handles partially filled windows correctly. It already achieves \(O(1)\) time per call and \(O(\text{size})\) space; the only useful polish is adding the -> float return annotation.
from collections import deque
class MovingAverage:
def __init__(self, size: int):
self.size = size
self.window_sum = 0
self.q = deque()
def next(self, val: int):
self.q.append(val)
self.window_sum += val
if len(self.q) > self.size:
self.window_sum -= self.q.popleft()
return self.window_sum / len(self.q)
Extra¶
Problem description¶
Given a stream of integers and a window size, calculate the moving average of all integers in the sliding window.
Implement the MovingAverage class:
MovingAverage(int size)Initializes the object with the size of the windowsize.double next(int val)Returns the moving average of the lastsizevalues of the stream.
Example 1:
Input
["MovingAverage", "next", "next", "next", "next"]
[[3], [1], [10], [3], [5]]
Output
[null, 1.0, 5.5, 4.66667, 6.0]
Explanation
MovingAverage movingAverage = new MovingAverage(3);
movingAverage.next(1); // return 1.0 = 1 / 1
movingAverage.next(10); // return 5.5 = (1 + 10) / 2
movingAverage.next(3); // return 4.66667 = (1 + 10 + 3) / 3
movingAverage.next(5); // return 6.0 = (10 + 3 + 5) / 3
Constraints:
1 <= size <= 1000-10^5 <= val <= 10^5- At most
10^4calls will be made tonext.