本题如果按照从左到右按个检查是否为0,挨个翻转K个长度,会超时。可以使用滑动窗口解决此题。
原理:位置为i的元素的值为0或1,会受到前K-1个元素的影响。
前K-1个元素如果翻转了偶数次,那么A[i]并不会改变;
前K-1个元素如果翻转了奇数次,那么A[i]会改变。
那么该元素是否需要翻转,只有两种情况:
1. A[i]为0,且前K-1个元素翻转了偶数次
2. A[i]为1,且前K-1个元素翻转了奇数次
得判断需要翻转的依据:翻转次数%2 == A[i] 那么需要翻转。
全部翻转为1的成功标志是:数组从头遍历到了结束。
失败的标志是:当元素下标加K已经超出数组长度,且该元素仍需要翻转,那么直接return -1。
此处用队列模拟滑动窗口,若遇到需要翻转的元素,则将该元素的下标入队,用以记录翻转的次数 即 队列的长度。
注:当队列的头元素(代表数组中该元素的下标)+K <= i时,说明这个元素的翻转并没有影响到A[i]的值,所以此时应当将其移除队列。
代码:
public int minKBitFlips(int[] A, int K) {
Queue<Integer> queue = new LinkedList<>();
int i = 0;
int count = 0;
while (i < A.length) {
if (queue.size() % 2 == A[i]) {
if (i + K > A.length) {
return -1;
}
queue.offer(i);
count++;
}
i++;
if (!queue.isEmpty() && queue.peek() + K <= i) {
queue.poll();
}
}
return count;
}