Welcome to Subscribe On Youtube
346. Moving Average from Data Stream
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-105 <= val <= 105- At most
104calls will be made tonext.
Solutions
This solution implements a moving average data structure that supports a method next(val) where val is an integer representing the next number in the data stream.
Class Initialization: __init__(self, size: int)
self.arr: Initializes an array of lengthsizefilled with zeros. This array serves as a circular buffer to hold the lastNvalues inserted, whereNis the specifiedsize.self.s: Initializes the sum of numbers currently in the circular buffer to0. This sum is used to efficiently compute the moving average.self.cnt: A counter to keep track of the total number of values that have been inserted so far. It helps in managing the circular nature ofself.arrand calculating the average correctly during the initial phase when the buffer is not yet full.
Method: next(self, val: int) -> float
- Circular Array Indexing:
idx = self.cnt % len(self.arr)calculates the index at which the new value should be inserted. This calculation ensures that the array is used as a circular buffer, overwriting the oldest data points with new ones once the buffer size (size) is exceeded. - Updating Sum: The new value
valis added toself.s, and the value being overwritten inself.arris subtracted fromself.s. This keepsself.sas the sum of all numbers currently in the buffer. - Inserting New Value: The new value
valis stored in the array at the calculated indexidx. - Incrementing Counter: The counter
self.cntis incremented by1to reflect the insertion of a new data point. - Calculating and Returning Moving Average: The method returns the moving average of the last
Nvalues. It dividesself.sbymin(self.cnt, len(self.arr))to ensure the correct average is calculated:- During the initial phase (when fewer than
Nvalues have been inserted), it divides byself.cntto average only the values that have been inserted. - Once the buffer is full (
self.cnt >= N), it divides bylen(self.arr)(N) to calculate the average of the lastNvalues.
- During the initial phase (when fewer than
-
class MovingAverage { private int[] arr; private int s; private int cnt; public MovingAverage(int size) { arr = new int[size]; } public double next(int val) { int idx = cnt % arr.length; s += val - arr[idx]; arr[idx] = val; ++cnt; return s * 1.0 / Math.min(cnt, arr.length); } } /** * Your MovingAverage object will be instantiated and called as such: * MovingAverage obj = new MovingAverage(size); * double param_1 = obj.next(val); */ -
class MovingAverage { public: MovingAverage(int size) { arr.resize(size); } double next(int val) { int idx = cnt % arr.size(); s += val - arr[idx]; arr[idx] = val; ++cnt; return (double) s / min(cnt, (int) arr.size()); } private: vector<int> arr; int cnt = 0; int s = 0; }; /** * Your MovingAverage object will be instantiated and called as such: * MovingAverage* obj = new MovingAverage(size); * double param_1 = obj->next(val); */ -
class MovingAverage: def __init__(self, size: int): self.arr = [0] * size self.s = 0 self.cnt = 0 def next(self, val: int) -> float: idx = self.cnt % len(self.arr) # circular array self.s += val - self.arr[idx] self.arr[idx] = val self.cnt += 1 return self.s / min(self.cnt, len(self.arr)) # Your MovingAverage object will be instantiated and called as such: # obj = MovingAverage(size) # param_1 = obj.next(val) ############ from collections import deque # with no sum variable, calculate on the fly class MovingAverage: def __init__(self, size: int): self.queue = deque() self.size = size self.avg = 0 def next(self, val: int) -> float: if len(self.queue) < self.size: self.queue.append(val) self.avg = sum(self.queue) / len(self.queue) return self.avg else: head = self.queue.popleft() self.queue.append(val) minus = head / self.size add = val / self.size self.avg = self.avg + add - minus return self.avg ############ from collections import deque class MovingAverage(object): def __init__(self, size): """ Initialize your data structure here. :type size: int """ self.windowSize = size self.windowSum = 0.0 self.data = deque([]) def next(self, val): """ :type val: int :rtype: float """ self.windowSum += val data = self.data leftTop = 0 if len(data) >= self.windowSize: leftTop = data.popleft() data.append(val) self.windowSum -= leftTop if len(data) < self.windowSize: return self.windowSum / len(data) return self.windowSum / self.windowSize # Your MovingAverage object will be instantiated and called as such: # obj = MovingAverage(size) # param_1 = obj.next(val) -
type MovingAverage struct { arr []int cnt int s int } func Constructor(size int) MovingAverage { arr := make([]int, size) return MovingAverage{arr, 0, 0} } func (this *MovingAverage) Next(val int) float64 { idx := this.cnt % len(this.arr) this.s += val - this.arr[idx] this.arr[idx] = val this.cnt++ return float64(this.s) / float64(min(this.cnt, len(this.arr))) } /** * Your MovingAverage object will be instantiated and called as such: * obj := Constructor(size); * param_1 := obj.Next(val); */ -
class MovingAverage { private s: number = 0; private cnt: number = 0; private data: number[]; constructor(size: number) { this.data = Array(size).fill(0); } next(val: number): number { const i = this.cnt % this.data.length; this.s += val - this.data[i]; this.data[i] = val; this.cnt++; return this.s / Math.min(this.cnt, this.data.length); } } /** * Your MovingAverage object will be instantiated and called as such: * var obj = new MovingAverage(size) * var param_1 = obj.next(val) */