From 29b56a3fde2658cdc3b06ce42669c2f1596d19e5 Mon Sep 17 00:00:00 2001 From: acbin <44314231+acbin@users.noreply.github.com> Date: Thu, 20 Mar 2025 07:43:54 +0000 Subject: [PATCH] feat: add solutions to lc problem: No.0346 No.0346.Moving Average from Data Stream --- .../README.md | 125 +++++++++++++---- .../README_EN.md | 129 ++++++++++++++---- .../Solution.cpp | 14 +- .../Solution.go | 19 +-- .../Solution.java | 12 +- .../Solution.py | 11 +- .../Solution.ts | 23 ++++ .../Solution2.ts | 24 ++++ 8 files changed, 274 insertions(+), 83 deletions(-) create mode 100644 solution/0300-0399/0346.Moving Average from Data Stream/Solution.ts create mode 100644 solution/0300-0399/0346.Moving Average from Data Stream/Solution2.ts diff --git a/solution/0300-0399/0346.Moving Average from Data Stream/README.md b/solution/0300-0399/0346.Moving Average from Data Stream/README.md index efb6c61d85aec..2a781655610a2 100644 --- a/solution/0300-0399/0346.Moving Average from Data Stream/README.md +++ b/solution/0300-0399/0346.Moving Average from Data Stream/README.md @@ -65,23 +65,30 @@ movingAverage.next(5); // 返回 6.0 = (10 + 3 + 5) / 3 ### 方法一:循环数组 +我们定义一个变量 $\textit{s}$,用于计算当前最后 $\textit{size}$ 个元素的和,用一个变量 $\textit{cnt}$ 记录当前元素的总数。另外,我们用一个长度为 $\textit{size}$ 的数组 $\textit{data}$ 记录每个位置的元素对应的值。 + +调用 $\textit{next}$ 函数时,我们先计算出 $\textit{val}$ 要存放的下标 $i$,然后我们更新元素和 $s$,并且将下标 $i$ 处的值设置为 $\textit{val}$,同时将元素的个数加一。最后,我们返回 $\frac{s}{\min(\textit{cnt}, \textit{size})}$ 的值即可。 + +时间复杂度 $O(1)$,空间复杂度 $O(n)$,其中 $n$ 是题目给定的整数 $\textit{size}$。 + #### Python3 ```python class MovingAverage: + def __init__(self, size: int): - self.arr = [0] * size self.s = 0 + self.data = [0] * size self.cnt = 0 def next(self, val: int) -> float: - idx = self.cnt % len(self.arr) - self.s += val - self.arr[idx] - self.arr[idx] = val + i = self.cnt % len(self.data) + self.s += val - self.data[i] + self.data[i] = val self.cnt += 1 - return self.s / min(self.cnt, len(self.arr)) + return self.s / min(self.cnt, len(self.data)) # Your MovingAverage object will be instantiated and called as such: @@ -93,20 +100,20 @@ class MovingAverage: ```java class MovingAverage { - private int[] arr; private int s; private int cnt; + private int[] data; public MovingAverage(int size) { - arr = new int[size]; + data = new int[size]; } public double next(int val) { - int idx = cnt % arr.length; - s += val - arr[idx]; - arr[idx] = val; + int i = cnt % data.length; + s += val - data[i]; + data[i] = val; ++cnt; - return s * 1.0 / Math.min(cnt, arr.length); + return s * 1.0 / Math.min(cnt, data.length); } } @@ -123,21 +130,21 @@ class MovingAverage { class MovingAverage { public: MovingAverage(int size) { - arr.resize(size); + data.resize(size); } double next(int val) { - int idx = cnt % arr.size(); - s += val - arr[idx]; - arr[idx] = val; + int i = cnt % data.size(); + s += val - data[i]; + data[i] = val; ++cnt; - return (double) s / min(cnt, (int) arr.size()); + return s * 1.0 / min(cnt, (int) data.size()); } private: - vector arr; - int cnt = 0; int s = 0; + int cnt = 0; + vector data; }; /** @@ -151,22 +158,23 @@ private: ```go type MovingAverage struct { - arr []int - cnt int - s int + s int + cnt int + data []int } func Constructor(size int) MovingAverage { - arr := make([]int, size) - return MovingAverage{arr, 0, 0} + return MovingAverage{ + data: make([]int, size), + } } func (this *MovingAverage) Next(val int) float64 { - idx := this.cnt % len(this.arr) - this.s += val - this.arr[idx] - this.arr[idx] = val + i := this.cnt % len(this.data) + this.s += val - this.data[i] + this.data[i] = val this.cnt++ - return float64(this.s) / float64(min(this.cnt, len(this.arr))) + return float64(this.s) / float64(min(this.cnt, len(this.data))) } /** @@ -176,6 +184,34 @@ func (this *MovingAverage) Next(val int) float64 { */ ``` +#### TypeScript + +```ts +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) + */ +``` + @@ -184,6 +220,12 @@ func (this *MovingAverage) Next(val int) float64 { ### 方法二:队列 +我们可以使用一个队列 $\textit{q}$ 来存储最后 $\textit{size}$ 个元素,同时用一个变量 $\textit{s}$ 来记录这 $\textit{size}$ 个元素的和。 + +在调用 $\textit{next}$ 函数时,我们首先判断队列 $\textit{q}$ 的长度是否等于 $\textit{size}$,如果等于 $\textit{size}$,则将队列 $\textit{q}$ 的头部元素出队,并且更新 $\textit{s}$ 的值。然后将 $\textit{val}$ 入队,并且更新 $\textit{s}$ 的值。最后返回 $\frac{s}{\text{len}(q)}$ 的值即可。 + +时间复杂度 $O(1)$,空间复杂度 $O(n)$,其中 $n$ 是题目给定的整数 $\textit{size}$。 + #### Python3 @@ -299,6 +341,35 @@ func (this *MovingAverage) Next(val int) float64 { */ ``` +#### TypeScript + +```ts +class MovingAverage { + private q: number[] = []; + private s: number = 0; + private n: number; + + constructor(size: number) { + this.n = size; + } + + next(val: number): number { + if (this.q.length === this.n) { + this.s -= this.q.shift()!; + } + this.q.push(val); + this.s += val; + return this.s / this.q.length; + } +} + +/** + * Your MovingAverage object will be instantiated and called as such: + * var obj = new MovingAverage(size) + * var param_1 = obj.next(val) + */ +``` + diff --git a/solution/0300-0399/0346.Moving Average from Data Stream/README_EN.md b/solution/0300-0399/0346.Moving Average from Data Stream/README_EN.md index e6c04298ab273..68d0a084b5d68 100644 --- a/solution/0300-0399/0346.Moving Average from Data Stream/README_EN.md +++ b/solution/0300-0399/0346.Moving Average from Data Stream/README_EN.md @@ -61,7 +61,13 @@ movingAverage.next(5); // return 6.0 = (10 + 3 + 5) / 3 -### Solution 1 +### Solution 1: Circular Array + +We define a variable $\textit{s}$ to calculate the sum of the last $\textit{size}$ elements, and a variable $\textit{cnt}$ to record the total number of current elements. Additionally, we use an array $\textit{data}$ of length $\textit{size}$ to record the value of each element at each position. + +When calling the $\textit{next}$ function, we first calculate the index $i$ where $\textit{val}$ should be stored, then update the sum $s$, set the value at index $i$ to $\textit{val}$, and increment the element count by one. Finally, we return the value of $\frac{s}{\min(\textit{cnt}, \textit{size})}$. + +The time complexity is $O(1)$, and the space complexity is $O(n)$, where $n$ is the integer $\textit{size}$ given in the problem. @@ -69,17 +75,18 @@ movingAverage.next(5); // return 6.0 = (10 + 3 + 5) / 3 ```python class MovingAverage: + def __init__(self, size: int): - self.arr = [0] * size self.s = 0 + self.data = [0] * size self.cnt = 0 def next(self, val: int) -> float: - idx = self.cnt % len(self.arr) - self.s += val - self.arr[idx] - self.arr[idx] = val + i = self.cnt % len(self.data) + self.s += val - self.data[i] + self.data[i] = val self.cnt += 1 - return self.s / min(self.cnt, len(self.arr)) + return self.s / min(self.cnt, len(self.data)) # Your MovingAverage object will be instantiated and called as such: @@ -91,20 +98,20 @@ class MovingAverage: ```java class MovingAverage { - private int[] arr; private int s; private int cnt; + private int[] data; public MovingAverage(int size) { - arr = new int[size]; + data = new int[size]; } public double next(int val) { - int idx = cnt % arr.length; - s += val - arr[idx]; - arr[idx] = val; + int i = cnt % data.length; + s += val - data[i]; + data[i] = val; ++cnt; - return s * 1.0 / Math.min(cnt, arr.length); + return s * 1.0 / Math.min(cnt, data.length); } } @@ -121,21 +128,21 @@ class MovingAverage { class MovingAverage { public: MovingAverage(int size) { - arr.resize(size); + data.resize(size); } double next(int val) { - int idx = cnt % arr.size(); - s += val - arr[idx]; - arr[idx] = val; + int i = cnt % data.size(); + s += val - data[i]; + data[i] = val; ++cnt; - return (double) s / min(cnt, (int) arr.size()); + return s * 1.0 / min(cnt, (int) data.size()); } private: - vector arr; - int cnt = 0; int s = 0; + int cnt = 0; + vector data; }; /** @@ -149,22 +156,23 @@ private: ```go type MovingAverage struct { - arr []int - cnt int - s int + s int + cnt int + data []int } func Constructor(size int) MovingAverage { - arr := make([]int, size) - return MovingAverage{arr, 0, 0} + return MovingAverage{ + data: make([]int, size), + } } func (this *MovingAverage) Next(val int) float64 { - idx := this.cnt % len(this.arr) - this.s += val - this.arr[idx] - this.arr[idx] = val + i := this.cnt % len(this.data) + this.s += val - this.data[i] + this.data[i] = val this.cnt++ - return float64(this.s) / float64(min(this.cnt, len(this.arr))) + return float64(this.s) / float64(min(this.cnt, len(this.data))) } /** @@ -174,13 +182,47 @@ func (this *MovingAverage) Next(val int) float64 { */ ``` +#### TypeScript + +```ts +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) + */ +``` + -### Solution 2 +### Solution 2: Queue + +We can use a queue $\textit{q}$ to store the last $\textit{size}$ elements, and a variable $\textit{s}$ to record the sum of these $\textit{size}$ elements. + +When calling the $\textit{next}$ function, we first check if the length of the queue $\textit{q}$ is equal to $\textit{size}$. If it is, we dequeue the front element of the queue $\textit{q}$ and update the value of $\textit{s}$. Then we enqueue $\textit{val}$ and update the value of $\textit{s}$. Finally, we return the value of $\frac{s}{\text{len}(q)}$. + +The time complexity is $O(1)$, and the space complexity is $O(n)$, where $n$ is the integer $\textit{size}$ given in the problem. @@ -297,6 +339,35 @@ func (this *MovingAverage) Next(val int) float64 { */ ``` +#### TypeScript + +```ts +class MovingAverage { + private q: number[] = []; + private s: number = 0; + private n: number; + + constructor(size: number) { + this.n = size; + } + + next(val: number): number { + if (this.q.length === this.n) { + this.s -= this.q.shift()!; + } + this.q.push(val); + this.s += val; + return this.s / this.q.length; + } +} + +/** + * Your MovingAverage object will be instantiated and called as such: + * var obj = new MovingAverage(size) + * var param_1 = obj.next(val) + */ +``` + diff --git a/solution/0300-0399/0346.Moving Average from Data Stream/Solution.cpp b/solution/0300-0399/0346.Moving Average from Data Stream/Solution.cpp index 2a9a16e4faee5..6576b9dc8630a 100644 --- a/solution/0300-0399/0346.Moving Average from Data Stream/Solution.cpp +++ b/solution/0300-0399/0346.Moving Average from Data Stream/Solution.cpp @@ -1,21 +1,21 @@ class MovingAverage { public: MovingAverage(int size) { - arr.resize(size); + data.resize(size); } double next(int val) { - int idx = cnt % arr.size(); - s += val - arr[idx]; - arr[idx] = val; + int i = cnt % data.size(); + s += val - data[i]; + data[i] = val; ++cnt; - return (double) s / min(cnt, (int) arr.size()); + return s * 1.0 / min(cnt, (int) data.size()); } private: - vector arr; - int cnt = 0; int s = 0; + int cnt = 0; + vector data; }; /** diff --git a/solution/0300-0399/0346.Moving Average from Data Stream/Solution.go b/solution/0300-0399/0346.Moving Average from Data Stream/Solution.go index ec727ba1c0a94..5dcabe9e9361e 100644 --- a/solution/0300-0399/0346.Moving Average from Data Stream/Solution.go +++ b/solution/0300-0399/0346.Moving Average from Data Stream/Solution.go @@ -1,20 +1,21 @@ type MovingAverage struct { - arr []int - cnt int - s int + s int + cnt int + data []int } func Constructor(size int) MovingAverage { - arr := make([]int, size) - return MovingAverage{arr, 0, 0} + return MovingAverage{ + data: make([]int, size), + } } func (this *MovingAverage) Next(val int) float64 { - idx := this.cnt % len(this.arr) - this.s += val - this.arr[idx] - this.arr[idx] = val + i := this.cnt % len(this.data) + this.s += val - this.data[i] + this.data[i] = val this.cnt++ - return float64(this.s) / float64(min(this.cnt, len(this.arr))) + return float64(this.s) / float64(min(this.cnt, len(this.data))) } /** diff --git a/solution/0300-0399/0346.Moving Average from Data Stream/Solution.java b/solution/0300-0399/0346.Moving Average from Data Stream/Solution.java index f9e90a100d6e2..d53353922e460 100644 --- a/solution/0300-0399/0346.Moving Average from Data Stream/Solution.java +++ b/solution/0300-0399/0346.Moving Average from Data Stream/Solution.java @@ -1,18 +1,18 @@ class MovingAverage { - private int[] arr; private int s; private int cnt; + private int[] data; public MovingAverage(int size) { - arr = new int[size]; + data = new int[size]; } public double next(int val) { - int idx = cnt % arr.length; - s += val - arr[idx]; - arr[idx] = val; + int i = cnt % data.length; + s += val - data[i]; + data[i] = val; ++cnt; - return s * 1.0 / Math.min(cnt, arr.length); + return s * 1.0 / Math.min(cnt, data.length); } } diff --git a/solution/0300-0399/0346.Moving Average from Data Stream/Solution.py b/solution/0300-0399/0346.Moving Average from Data Stream/Solution.py index 883ed1d768a19..edc9e4f84623b 100644 --- a/solution/0300-0399/0346.Moving Average from Data Stream/Solution.py +++ b/solution/0300-0399/0346.Moving Average from Data Stream/Solution.py @@ -1,15 +1,16 @@ class MovingAverage: + def __init__(self, size: int): - self.arr = [0] * size self.s = 0 + self.data = [0] * size self.cnt = 0 def next(self, val: int) -> float: - idx = self.cnt % len(self.arr) - self.s += val - self.arr[idx] - self.arr[idx] = val + i = self.cnt % len(self.data) + self.s += val - self.data[i] + self.data[i] = val self.cnt += 1 - return self.s / min(self.cnt, len(self.arr)) + return self.s / min(self.cnt, len(self.data)) # Your MovingAverage object will be instantiated and called as such: diff --git a/solution/0300-0399/0346.Moving Average from Data Stream/Solution.ts b/solution/0300-0399/0346.Moving Average from Data Stream/Solution.ts new file mode 100644 index 0000000000000..db54902553b61 --- /dev/null +++ b/solution/0300-0399/0346.Moving Average from Data Stream/Solution.ts @@ -0,0 +1,23 @@ +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) + */ diff --git a/solution/0300-0399/0346.Moving Average from Data Stream/Solution2.ts b/solution/0300-0399/0346.Moving Average from Data Stream/Solution2.ts new file mode 100644 index 0000000000000..52a3940d0d2e8 --- /dev/null +++ b/solution/0300-0399/0346.Moving Average from Data Stream/Solution2.ts @@ -0,0 +1,24 @@ +class MovingAverage { + private q: number[] = []; + private s: number = 0; + private n: number; + + constructor(size: number) { + this.n = size; + } + + next(val: number): number { + if (this.q.length === this.n) { + this.s -= this.q.shift()!; + } + this.q.push(val); + this.s += val; + return this.s / this.q.length; + } +} + +/** + * Your MovingAverage object will be instantiated and called as such: + * var obj = new MovingAverage(size) + * var param_1 = obj.next(val) + */