avatar

LeetCode-995 K 连续位的最小翻转次数

📝题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 0。

返回所需的 K 位翻转的最小次数,以便数组没有值为 0 的元素。如果不可能,返回 -1。 

示例 1:

输入:A = [0,1,0], K = 1
输出:2
解释:先翻转 A[0],然后翻转 A[2]。

示例 2:

输入:A = [1,1,0], K = 2
输出:-1
解释:无论我们怎样翻转大小为 2 的子数组,我们都不能使数组变为 [1,1,1]。

示例 3:

输入:A = [0,0,0,1,0,1,1,0], K = 3
输出:3
解释:
翻转 A[0],A[1],A[2]: A变成 [1,1,1,1,0,1,1,0]
翻转 A[4],A[5],A[6]: A变成 [1,1,1,1,1,0,0,0]
翻转 A[5],A[6],A[7]: A变成 [1,1,1,1,1,1,1,1]

限制:
· 1 <= A.length <= 30000
· 1 <= K <= A.length


📝思路

最直接的思路是,用一个长度为 K 的窗口滑动遍历所有元素,根据最左侧元素的值来决定是否翻转窗口内所有元素,时间复杂度为O(N K),看似不差,但在本题的限制下超时了(毕竟 K 很大的情况下O(N K) 和 O(N)还是有一定差距的)…
既然如此,那便要通过“消灭” K 来省时,上述时间复杂度之所以出现了 K,是因为我们每次遍历可能会实际执行 K 次元素翻转,如果我们不对其翻转呢?


📝题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int minKBitFlips(vector<int>& A, int K) {
int len = A.size();
queue<int> q;
int res = 0;
for (int i = 0; i < len; ++i) {
while (!q.empty() && q.front() + K <= i) {
q.pop();
}
if (q.size() % 2 == A[i]) {
if (i + K > len) return -1;
q.push(i);
res++;
}
}
return res;
}
Author:WhiteBeerHouse
Link:https://github.com/WhiteBeerHouse/WhiteBeerHouse.github.io/tree/master/2021/02/18/LeetCode-995-K%20%E8%BF%9E%E7%BB%AD%E4%BD%8D%E7%9A%84%E6%9C%80%E5%B0%8F%E7%BF%BB%E8%BD%AC%E6%AC%A1%E6%95%B0/
Copyright Notice:All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.