Skip to content

Commit 99fdb7b

Browse files
authoredSep 2, 2023
feat: add solutions to lc problem: No.0644 (#1566)
1 parent 89ab7a0 commit 99fdb7b

File tree

7 files changed

+570
-1
lines changed

7 files changed

+570
-1
lines changed
 

‎solution/0600-0699/0644.Maximum Average Subarray II/README.md

+218
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,240 @@
4646

4747
<!-- 这里可写通用的实现逻辑 -->
4848

49+
**方法一:二分查找**
50+
51+
我们注意到,如果一个长度大于等于 $k$ 的子数组的平均值为 $v$,那么最大平均数一定大于等于 $v$,否则最大平均数一定小于 $v$。因此,我们可以使用二分查找的方法找出最大平均数。
52+
53+
我们考虑二分查找的左右边界分别是什么?左边界 $l$ 一定是数组中的最小值,而右边界 $r$ 则是数组中的最大值。接下来,我们二分查找中点 $mid$,判断是否存在长度大于等于 $k$ 的子数组的平均值大于等于 $mid$。如果存在,那么我们就将左边界 $l$ 更新为 $mid$,否则我们就将右边界 $r$ 更新为 $mid$。当左边界和右边界的差小于一个极小的非负数,即 $r - l < \epsilon$ 时,我们就可以得到最大平均数,其中 $\epsilon$ 表示一个极小的正数,可以取 $10^{-5}$。
54+
55+
问题的关键在于如何判断一个长度大于等于 $k$ 的子数组的平均值是否大于等于 $v$。
56+
57+
我们假设在数组 $nums$ 中,存在一个长度为 $j$ 的子数组,元素分别为 $a_1, a_2, \cdots, a_j$,满足其平均值大于等于 $v$,即:
58+
59+
$$
60+
\frac{a_1 + a_2 + \cdots + a_j}{j} \geq v
61+
$$
62+
63+
那么:
64+
65+
$$
66+
a_1 + a_2 + \cdots + a_j \geq v \times j
67+
$$
68+
69+
即:
70+
71+
$$
72+
(a_1 - v) + (a_2 - v) + \cdots + (a_j - v) \geq 0
73+
$$
74+
75+
可以发现,如果我们将数组 $nums$ 中的每个元素都减去 $v$,那么原问题就转换成了一个求长度大于等于 $k$ 的子数组的元素和是否大于等于 $0$ 的问题。我们可以使用滑动窗口来解决这个问题。
76+
77+
我们先计算得到数组前 $k$ 个元素与 $v$ 的差值之和 $s$,如果 $s \geq 0$,那么就说明存在长度大于等于 $k$ 的子数组的元素和大于等于 $0$。
78+
79+
否则,我们继续往后遍历元素 $nums[j]$,假设当前前 $j$ 项元素与 $v$ 的差值之和为 $s_j$,那么我们可以维护在 $[0,..j-k]$ 范围内元素的前缀和与 $v$ 的差值之和的最小值 $mi$,如果存在 $s_j \geq mi$,那么就说明存在长度大于等于 $k$ 的子数组的元素和大于等于 $0$,返回 $true$。
80+
81+
否则,我们继续往后遍历元素 $nums[j]$,直到遍历完整个数组。
82+
83+
时间复杂度 $O(n \times \log M)$,其中 $n$ 和 $M$ 分别是数组 $nums$ 的长度以及数组中的最大值和最小值的差值。空间复杂度 $O(1)$。
84+
4985
<!-- tabs:start -->
5086

5187
### **Python3**
5288

5389
<!-- 这里可写当前语言的特殊实现逻辑 -->
5490

5591
```python
92+
class Solution:
93+
def findMaxAverage(self, nums: List[int], k: int) -> float:
94+
def check(v: float) -> bool:
95+
s = sum(nums[:k]) - k * v
96+
if s >= 0:
97+
return True
98+
t = mi = 0
99+
for i in range(k, len(nums)):
100+
s += nums[i] - v
101+
t += nums[i - k] - v
102+
mi = min(mi, t)
103+
if s >= mi:
104+
return True
105+
return False
56106

107+
eps = 1e-5
108+
l, r = min(nums), max(nums)
109+
while r - l >= eps:
110+
mid = (l + r) / 2
111+
if check(mid):
112+
l = mid
113+
else:
114+
r = mid
115+
return l
57116
```
58117

59118
### **Java**
60119

61120
<!-- 这里可写当前语言的特殊实现逻辑 -->
62121

63122
```java
123+
class Solution {
124+
public double findMaxAverage(int[] nums, int k) {
125+
double eps = 1e-5;
126+
double l = 1e10, r = -1e10;
127+
for (int x : nums) {
128+
l = Math.min(l, x);
129+
r = Math.max(r, x);
130+
}
131+
while (r - l >= eps) {
132+
double mid = (l + r) / 2;
133+
if (check(nums, k, mid)) {
134+
l = mid;
135+
} else {
136+
r = mid;
137+
}
138+
}
139+
return l;
140+
}
141+
142+
private boolean check(int[] nums, int k, double v) {
143+
double s = 0;
144+
for (int i = 0; i < k; ++i) {
145+
s += nums[i] - v;
146+
}
147+
if (s >= 0) {
148+
return true;
149+
}
150+
double t = 0;
151+
double mi = 0;
152+
for (int i = k; i < nums.length; ++i) {
153+
s += nums[i] - v;
154+
t += nums[i - k] - v;
155+
mi = Math.min(mi, t);
156+
if (s >= mi) {
157+
return true;
158+
}
159+
}
160+
return false;
161+
}
162+
}
163+
```
164+
165+
### **C++**
166+
167+
```cpp
168+
class Solution {
169+
public:
170+
double findMaxAverage(vector<int>& nums, int k) {
171+
double eps = 1e-5;
172+
double l = *min_element(nums.begin(), nums.end());
173+
double r = *max_element(nums.begin(), nums.end());
174+
auto check = [&](double v) {
175+
double s = 0;
176+
for (int i = 0; i < k; ++i) {
177+
s += nums[i] - v;
178+
}
179+
if (s >= 0) {
180+
return true;
181+
}
182+
double t = 0;
183+
double mi = 0;
184+
for (int i = k; i < nums.size(); ++i) {
185+
s += nums[i] - v;
186+
t += nums[i - k] - v;
187+
mi = min(mi, t);
188+
if (s >= mi) {
189+
return true;
190+
}
191+
}
192+
return false;
193+
};
194+
while (r - l >= eps) {
195+
double mid = (l + r) / 2;
196+
if (check(mid)) {
197+
l = mid;
198+
} else {
199+
r = mid;
200+
}
201+
}
202+
return l;
203+
}
204+
};
205+
```
206+
207+
### **Go**
208+
209+
```go
210+
func findMaxAverage(nums []int, k int) float64 {
211+
eps := 1e-5
212+
l, r := 1e9, -1e9
213+
for _, x := range nums {
214+
l = math.Min(l, float64(x))
215+
r = math.Max(r, float64(x))
216+
}
217+
check := func(v float64) bool {
218+
s := 0.0
219+
for _, x := range nums[:k] {
220+
s += float64(x) - v
221+
}
222+
if s >= 0 {
223+
return true
224+
}
225+
t := 0.0
226+
mi := 0.0
227+
for i := k; i < len(nums); i++ {
228+
s += float64(nums[i]) - v
229+
t += float64(nums[i-k]) - v
230+
mi = math.Min(mi, t)
231+
if s >= mi {
232+
return true
233+
}
234+
}
235+
return false
236+
}
237+
for r-l >= eps {
238+
mid := (l + r) / 2
239+
if check(mid) {
240+
l = mid
241+
} else {
242+
r = mid
243+
}
244+
}
245+
return l
246+
}
247+
```
248+
249+
### **TypeScript**
64250

251+
```ts
252+
function findMaxAverage(nums: number[], k: number): number {
253+
const eps = 1e-5;
254+
let l = Math.min(...nums);
255+
let r = Math.max(...nums);
256+
const check = (v: number): boolean => {
257+
let s = nums.slice(0, k).reduce((a, b) => a + b) - v * k;
258+
if (s >= 0) {
259+
return true;
260+
}
261+
let t = 0;
262+
let mi = 0;
263+
for (let i = k; i < nums.length; ++i) {
264+
s += nums[i] - v;
265+
t += nums[i - k] - v;
266+
mi = Math.min(mi, t);
267+
if (s >= mi) {
268+
return true;
269+
}
270+
}
271+
return false;
272+
};
273+
while (r - l >= eps) {
274+
const mid = (l + r) / 2;
275+
if (check(mid)) {
276+
l = mid;
277+
} else {
278+
r = mid;
279+
}
280+
}
281+
return l;
282+
}
65283
```
66284

67285
### **...**

0 commit comments

Comments
 (0)