题目链接:https://leetcode-cn.com/problems/minimum-number-of-k-consecutive-bit-flips/
第一道LeetCode困难题 AC 嘿嘿嘿
由于目标是把所有的0都变成1,所以从左向右遍历,只要看到0就翻转一次,维护长度为K的滑动窗口,当窗口到达数组最右端后,如果还存在 0,说明不可能全部翻转,返回 -1
但是滑动窗口右移的过程中会遇到一个问题,即每次翻转 k 个的操作,会超时(复杂度是 kN,应该会)。所以利用前缀和记录当前翻转的次数,由于某一个位置翻转只会影响到从该位置开始到该位置 + K - 1的位置结束,所以我们的前缀和数组也要用一个滑动窗口维护。
由于两个滑动窗口速度一样,相差恒定为k,所以可以合并在一起。
代码如下:
class Solution {
public:
int upanddown(int x, int cnt) { //判断当前数值加上翻转次数的结果
return (x + cnt) % 2;
}
int minKBitFlips(vector<int>& A, int K) {
int res = 0;
int l = 0, r = K - 1;
vector<int> cnt(A.size() + 1, 0);
int sum = 0;
while(r < A.size()) {
if(upanddown(A[l], sum) == 0) { //若需要翻转
res++; // 结果+1
cnt[l] = 1; // 记录当前位置需翻转
}
r++;
sum += cnt[l]; //前缀和滑动窗口,记录当前位置总翻转次数
l++;
if(l > K - 1) {
sum -= cnt[l - K]; //前缀和滑动窗口的更新
}
}
for(int i = l; i < A.size(); i++) { //遍历完成后,判断是否还存在0
if(upanddown(A[i], sum) == 0) {
return -1;
}
if(i + 1 > K - 1) {
sum -= cnt[i + 1 - K];
}
}
return res;
}
};