Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 99fdb7b

Browse files
feat: add solutions to lc problem: No.0644 (doocs#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‎

Lines changed: 218 additions & 0 deletions
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)

AltStyle によって変換されたページ (->オリジナル) /