Skip to content

Commit b6d9efd

Browse files
author
lucifer
committed
fix: typo
1 parent 05ced95 commit b6d9efd

File tree

1 file changed

+8
-6
lines changed

1 file changed

+8
-6
lines changed

problems/1004.max-consecutive-ones-iii.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,25 +58,27 @@ A[i] 为 0 或 1 
5858
相应地,我们需要记录移除窗口的是 0 还是 1:
5959

6060
- 如果是 1,我们什么都不做
61-
- 如果是 0,说明加进来的时候就是 1,加进来的时候我们 K 减去了 1,这个时候我们再加 1。
61+
- 如果是 0,说明加进来的时候就是 0,加进来的时候我们 K 减去了 1,这个时候我们再加回去 1。
62+
63+
如果 K 减少到负数,则收缩窗口大小。不断用满足条件的窗口大小更新答案即可。
6264

6365
### 为什么这种思路可行?
6466

6567
这其实就是滑动窗口的常见套路。 这种算法可行的根本原因在于其本身就是暴力枚举的优化。如果让你用最暴力的解法如何求解呢?无非就是枚举所有的子数组,这需要 $O(N^2)$ 的时间复杂度,接下来判断子数组是否满足**最多将 k 个 0 变成 1,子数组全部为 1**。如果满足则更新答案即可。 如何对暴力解进行优化呢?
6668

6769
比如现在是判断的子数组 A[2:3],我们计算出 A[2:3] 有一个 0,也就是说需要将一个 0 变成 1 才行。那么当我们继续判断子数组 A[2:4],我们只需要判断 A[4],同时结合 A[2:3]的计数信息即可。**滑动窗口就是专门优化这种每次只在端点变化,中间都不变,从而省去了中间即重复计算,进而将窗口内的计数信息从 O(w) 降低到 O(1)**,其中 w 为窗口大小。
6870

69-
接下来,我们继续优化。实际上也是没有必要两层循环枚举所有子数组的。而是在 $O(n)$ 的时间就可以枚举所有的合法子数组。为什么呢?你可以换个角度思考
71+
接下来,我们继续优化。实际上也是没有必要两层循环枚举所有子数组的。而是在 $O(n)$ 的时间就可以枚举所有的合法子数组。为什么呢?这是双指针的常见套路。其实你可以换个角度思考
7072

7173
所有的子数组就是
7274

7375
- 以索引 0 为右端点的所有子数组
74-
- - 以索引 1 为右端点的所有子数组
75-
- - 以索引 2 为右端点的所有子数组
76+
- 加上以索引 1 为右端点的所有子数组
77+
- 加上以索引 2 为右端点的所有子数组
7678
- ...
77-
- - 以索引 n - 1 为右端点的所有子数组,其中 n 为数组长度
79+
- 加上以索引 n - 1 为右端点的所有子数组,其中 n 为数组长度
7880

79-
这样的话我们就可以使用双指针技巧。右指针模拟右端点,使用左指针模拟左端点了。**如果以索引 i 为右端点的子数组 0 的个数不大于 k,那么左指针 l 没必要右移,因为当前右指针 r 和所有的索引 i, 其中 l <= i <= r 的组合 0 的个数都不会大于 k,而且子数组还更短了,不可能是答案,因此我们直接右移右指针,这是算法的关键**。通过这种方式算法的时间复杂度可从 $O(n^2)$ 降低到 $n$。
81+
这样的话我们就可以使用双指针技巧。右指针模拟右端点,使用左指针模拟左端点了。**如果以索引 i 为右端点的子数组 0 的个数不大于 k,那么左指针 l 没必要右移,因为当前右指针 r 和所有的索引 i, 其中 l <= i <= r 的组合 0 的个数都不会大于 k,但是子数组还更短了,不可能是答案,因此我们直接右移右指针,这是算法的关键**。通过这种方式算法的时间复杂度可从 $O(n^2)$ 降低到 $n$。
8082

8183
## 代码
8284

0 commit comments

Comments
 (0)