题目:
题解:
- 首先我们可以知道,对于每个位置而言,只有初始状态和总共被反转了多少次决定了自己最终的状态。另一方面,我们知道每一个长度为K的区间,最多只会被反转一次,因为两次反转后对最终结果没有影响。基于此,我们从前往后遍历数组,如果遇到一个0,我们将当前位置开始的长度为k区间的区间反转。如果遇到0时,剩下的区间长度不足K说明我们没有办法完成反转。但是如果我们每次反转当前区间时,将区间内每个数都取反,时间复杂度是O(n*k)的,毫无疑问这样超时了。
- 因此我们需要优化一下,我们再考虑每个位置上的元素,它只会被前面K - 1个元素是否被反转所影响,所以我们只需要知道前面k - 1个元素总共反转了多少次(更进一步的说我们只关心反转次数的奇偶性)。
- 我们使用一个队列保存i前面k - 1个位置有多少元素被反转了(队列的长度表示反转的次数)。0反转偶数次还是0,任需要反转;1反转了奇数次为0,也需要反转。只有0反转了奇数次变成了1和1反转了偶数次还是1不需要反转。如果最后k - 1个位置还有0的话说明失败。否则将i加入队列,更新答案。
代码如下:
class Solution {
public:
int minKBitFlips(vector<int>& A, int K) {
if(A.empty())return -1;
int result=0,N=A.size();
queue<int> window;//window用来存放被反转元素的下标,window的长度表示反转的次数
for(int i=0;i<N;++i)
{
//当下标之间的距离大于k时,需要移除队头下标了
while(!window.empty()&&window.front() + K <= i)
window.pop();
//当前位置的1反转奇数次为0,需要反转;当前位置的0反转偶数次还是为0,还是需要反转
if(A[i]==window.size()%2)
{
if(i+K>N)return -1;
window.push(i);
result++;
}
}
return result;
}
};