Skip to content

Commit 2a20e90

Browse files
committed
feat: add solutions to lc problem: No.0209
No.0209.Minimum Size Subarray Sum
1 parent 36ec8ed commit 2a20e90

File tree

8 files changed

+350
-296
lines changed

8 files changed

+350
-296
lines changed

solution/0200-0299/0209.Minimum Size Subarray Sum/README.md

+154-116
Original file line numberDiff line numberDiff line change
@@ -58,215 +58,228 @@
5858

5959
**方法一:前缀和 + 二分查找**
6060

61-
先求出数组的前缀和 `s`,然后根据 `s[j] - s[i] >= target` => `s[j] >= s[i] + target`,找出最小的一个 j,使得 `s[j]` 满足大于等于 `s[i] + target`,然后更新最小长度即可
61+
我们先预处理出数组 $nums$ 的前缀和数组 $s$,其中 $s[i]$ 表示数组 $nums$ 前 $i$ 项元素之和。由于数组 $nums$ 中的元素都是正整数,因此数组 $s$ 也是单调递增的。另外,我们初始化答案 $ans = n + 1$,其中 $n$ 为数组 $nums$ 的长度
6262

63-
时间复杂度 $O(NlogN)$。
63+
接下来,我们遍历前缀和数组 $s$,对于其中的每个元素 $s[i]$,我们可以通过二分查找的方法找到满足 $s[j] \geq s[i] + target$ 的最小下标 $j$,如果 $j \leq n$,则说明存在满足条件的子数组,我们可以更新答案,即 $ans = min(ans, j - i)$。
6464

65-
**方法二:滑动窗口**
65+
最后,如果 $ans \leq n$,则说明存在满足条件的子数组,返回 $ans$,否则返回 $0$。
6666

67-
使用指针 `left`, `right` 分别表示子数组的开始位置和结束位置,维护变量 `sum` 表示子数组 `nums[left...right]` 元素之和。初始时 `left`, `right` 均指向 0。每一次迭代,将 `nums[right]` 加到 `sum`,如果此时 `sum >= target`,更新最小长度即可。然后将 `sum` 减去 `nums[left]`,接着 `left` 指针右移直至 `sum < target`。每一次迭代最后,将 `right` 指针右移
67+
时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $nums$ 的长度
6868

69-
时间复杂度 $O(N)$。
69+
**方法二:双指针**
70+
71+
我们可以使用双指针 $j$ 和 $i$ 维护一个窗口,其中窗口中的所有元素之和小于 $target$。初始时 $j = 0$,答案 $ans = n + 1$,其中 $n$ 为数组 $nums$ 的长度。
72+
73+
接下来,指针 $i$ 从 $0$ 开始向右移动,每次移动一步,我们将指针 $i$ 对应的元素加入窗口,同时更新窗口中元素之和。如果窗口中元素之和大于等于 $target$,说明当前子数组满足条件,我们可以更新答案,即 $ans = min(ans, i - j + 1)$。然后我们不断地从窗口中移除元素 $nums[j]$,直到窗口中元素之和小于 $target$,然后重复上述过程。
74+
75+
最后,如果 $ans \leq n$,则说明存在满足条件的子数组,返回 $ans$,否则返回 $0$。
76+
77+
时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 $nums$ 的长度。
7078

7179
<!-- tabs:start -->
7280

7381
### **Python3**
7482

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

77-
前缀和 + 二分查找:
78-
7985
```python
8086
class Solution:
8187
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
82-
s = [0] + list(accumulate(nums))
8388
n = len(nums)
89+
s = list(accumulate(nums, initial=0))
8490
ans = n + 1
85-
for i, v in enumerate(s):
86-
t = v + target
87-
j = bisect_left(s, t)
88-
if j != n + 1:
91+
for i, x in enumerate(s):
92+
j = bisect_left(s, x + target)
93+
if j <= n:
8994
ans = min(ans, j - i)
90-
return 0 if ans == n + 1 else ans
95+
return ans if ans <= n else 0
9196
```
9297

93-
滑动窗口:
94-
9598
```python
9699
class Solution:
97100
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
98101
n = len(nums)
99-
left = right = 0
100-
sum, res = 0, n + 1
101-
while right < n:
102-
sum += nums[right]
103-
while sum >= target:
104-
res = min(res, right - left + 1)
105-
sum -= nums[left]
106-
left += 1
107-
right += 1
108-
return 0 if res == n + 1 else res
102+
ans = n + 1
103+
s = j = 0
104+
for i, x in enumerate(nums):
105+
s += x
106+
while j < n and s >= target:
107+
ans = min(ans, i - j + 1)
108+
s -= nums[j]
109+
j += 1
110+
return ans if ans <= n else 0
109111
```
110112

111113
### **Java**
112114

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

115-
前缀和 + 二分查找:
116-
117117
```java
118118
class Solution {
119119
public int minSubArrayLen(int target, int[] nums) {
120120
int n = nums.length;
121-
int[] s = new int[n + 1];
121+
long[] s = new long[n + 1];
122122
for (int i = 0; i < n; ++i) {
123123
s[i + 1] = s[i] + nums[i];
124124
}
125125
int ans = n + 1;
126-
for (int i = 0; i < n; ++i) {
127-
int t = s[i] + target;
128-
int left = 0, right = n + 1;
129-
while (left < right) {
130-
int mid = (left + right) >> 1;
131-
if (s[mid] >= t) {
132-
right = mid;
133-
} else {
134-
left = mid + 1;
135-
}
126+
for (int i = 0; i <= n; ++i) {
127+
int j = search(s, s[i] + target);
128+
if (j <= n) {
129+
ans = Math.min(ans, j - i);
136130
}
137-
if (left != n + 1) {
138-
ans = Math.min(ans, left - i);
131+
}
132+
return ans <= n ? ans : 0;
133+
}
134+
135+
private int search(long[] nums, long x) {
136+
int l = 0, r = nums.length;
137+
while (l < r) {
138+
int mid = (l + r) >> 1;
139+
if (nums[mid] >= x) {
140+
r = mid;
141+
} else {
142+
l = mid + 1;
139143
}
140144
}
141-
return ans == n + 1 ? 0 : ans;
145+
return l;
142146
}
143147
}
144148
```
145149

146-
滑动窗口:
147-
148150
```java
149151
class Solution {
150152
public int minSubArrayLen(int target, int[] nums) {
151153
int n = nums.length;
152-
int left = 0, right = 0;
153-
int sum = 0, res = n + 1;
154-
while (right < n) {
155-
sum += nums[right];
156-
while (sum >= target) {
157-
res = Math.min(res, right - left + 1);
158-
sum -= nums[left++];
154+
long s = 0;
155+
int ans = n + 1;
156+
for (int i = 0, j = 0; i < n; ++i) {
157+
s += nums[i];
158+
while (j < n && s >= target) {
159+
ans = Math.min(ans, i - j + 1);
160+
s -= nums[j++];
159161
}
160-
++right;
161162
}
162-
return res == n + 1 ? 0 : res;
163+
return ans <= n ? ans : 0;
163164
}
164165
}
165166
```
166167

167168
### **C++**
168169

169-
前缀和 + 二分查找:
170-
171170
```cpp
172171
class Solution {
173172
public:
174173
int minSubArrayLen(int target, vector<int>& nums) {
175174
int n = nums.size();
176-
vector<int> s(n + 1);
177-
for (int i = 0; i < n; ++i) s[i + 1] = s[i] + nums[i];
178-
int ans = n + 1;
175+
vector<long long> s(n + 1);
179176
for (int i = 0; i < n; ++i) {
180-
int t = s[i] + target;
181-
auto p = lower_bound(s.begin(), s.end(), t);
182-
if (p != s.end()) {
183-
int j = p - s.begin();
177+
s[i + 1] = s[i] + nums[i];
178+
}
179+
int ans = n + 1;
180+
for (int i = 0; i <= n; ++i) {
181+
int j = lower_bound(s.begin(), s.end(), s[i] + target) - s.begin();
182+
if (j <= n) {
184183
ans = min(ans, j - i);
185184
}
186185
}
187-
return ans == n + 1 ? 0 : ans;
186+
return ans <= n ? ans : 0;
188187
}
189188
};
190189
```
191190
192-
滑动窗口:
193-
194191
```cpp
195192
class Solution {
196193
public:
197194
int minSubArrayLen(int target, vector<int>& nums) {
198-
int left = 0, right;
199-
int sum = 0;
200-
int minlen = INT_MAX;
201-
202-
for (right = 0; right < nums.size(); right++) {
203-
sum += nums[right];
204-
while (left <= right && sum >= target) {
205-
minlen = min(minlen, right - left + 1);
206-
sum -= nums[left++];
195+
int n = nums.size();
196+
long long s = 0;
197+
int ans = n + 1;
198+
for (int i = 0, j = 0; i < n; ++i) {
199+
s += nums[i];
200+
while (j < n && s >= target) {
201+
ans = min(ans, i - j + 1);
202+
s -= nums[j++];
207203
}
208204
}
209-
210-
return minlen == INT_MAX ? 0 : minlen;
205+
return ans == n + 1 ? 0 : ans;
211206
}
212207
};
213208
```
214209

215210
### **Go**
216211

217-
前缀和 + 二分查找:
218-
219212
```go
220213
func minSubArrayLen(target int, nums []int) int {
221214
n := len(nums)
222215
s := make([]int, n+1)
223-
for i, v := range nums {
224-
s[i+1] = s[i] + v
216+
for i, x := range nums {
217+
s[i+1] = s[i] + x
225218
}
226219
ans := n + 1
227-
for i, v := range s {
228-
t := v + target
229-
left, right := 0, n+1
230-
for left < right {
231-
mid := (left + right) >> 1
232-
if s[mid] >= t {
233-
right = mid
234-
} else {
235-
left = mid + 1
236-
}
220+
for i, x := range s {
221+
j := sort.SearchInts(s, x+target)
222+
if j <= n {
223+
ans = min(ans, j-i)
237224
}
238-
if left != n+1 && ans > left-i {
239-
ans = left - i
225+
}
226+
if ans == n+1 {
227+
return 0
228+
}
229+
return ans
230+
}
231+
232+
func min(a, b int) int {
233+
if a < b {
234+
return a
235+
}
236+
return b
237+
}
238+
```
239+
240+
```go
241+
func minSubArrayLen(target int, nums []int) int {
242+
n := len(nums)
243+
s := 0
244+
ans := n + 1
245+
for i, j := 0, 0; i < n; i++ {
246+
s += nums[i]
247+
for s >= target {
248+
ans = min(ans, i-j+1)
249+
s -= nums[j]
250+
j++
240251
}
241252
}
242253
if ans == n+1 {
243254
return 0
244255
}
245256
return ans
246257
}
258+
259+
func min(a, b int) int {
260+
if a < b {
261+
return a
262+
}
263+
return b
264+
}
247265
```
248266

249267
### **C#**
250268

251-
滑动窗口:
252-
253269
```cs
254270
public class Solution {
255271
public int MinSubArrayLen(int target, int[] nums) {
256272
int n = nums.Length;
257-
int left = 0, right = 0;
258-
int sum = 0, res = n + 1;
259-
while (right < n)
260-
{
261-
sum += nums[right];
262-
while (sum >= target)
263-
{
264-
res = Math.Min(res, right - left + 1);
265-
sum -= nums[left++];
273+
long s = 0;
274+
int ans = n + 1;
275+
for (int i = 0, j = 0; i < n; ++i) {
276+
s += nums[i];
277+
while (s >= target) {
278+
ans = Math.Min(ans, i - j + 1);
279+
s -= nums[j++];
266280
}
267-
++right;
268281
}
269-
return res == n + 1 ? 0 : res;
282+
return ans == n + 1 ? 0 : ans;
270283
}
271284
}
272285
```
@@ -276,22 +289,47 @@ public class Solution {
276289
```ts
277290
function minSubArrayLen(target: number, nums: number[]): number {
278291
const n = nums.length;
279-
let res = n + 1;
280-
let sum = 0;
281-
let i = 0;
282-
for (let j = 0; j < n; j++) {
283-
sum += nums[j];
284-
while (sum >= target) {
285-
res = Math.min(res, j - i + 1);
286-
sum -= nums[i];
287-
i++;
292+
const s: number[] = new Array(n + 1).fill(0);
293+
for (let i = 0; i < n; ++i) {
294+
s[i + 1] = s[i] + nums[i];
295+
}
296+
let ans = n + 1;
297+
const search = (x: number) => {
298+
let l = 0;
299+
let r = n + 1;
300+
while (l < r) {
301+
const mid = (l + r) >>> 1;
302+
if (s[mid] >= x) {
303+
r = mid;
304+
} else {
305+
l = mid + 1;
306+
}
307+
}
308+
return l;
309+
};
310+
for (let i = 0; i <= n; ++i) {
311+
const j = search(s[i] + target);
312+
if (j <= n) {
313+
ans = Math.min(ans, j - i);
288314
}
289315
}
316+
return ans === n + 1 ? 0 : ans;
317+
}
318+
```
290319

291-
if (res === n + 1) {
292-
return 0;
320+
```ts
321+
function minSubArrayLen(target: number, nums: number[]): number {
322+
const n = nums.length;
323+
let s = 0;
324+
let ans = n + 1;
325+
for (let i = 0, j = 0; i < n; ++i) {
326+
s += nums[i];
327+
while (s >= target) {
328+
ans = Math.min(ans, i - j + 1);
329+
s -= nums[j++];
330+
}
293331
}
294-
return res;
332+
return ans === n + 1 ? 0 : ans;
295333
}
296334
```
297335

0 commit comments

Comments
 (0)