原题链接:995. Minimum Number of K Consecutive Bit Flips
- 核心思想: 具体的翻转次数并不重要,只需知道是奇数次还是偶数次即可
class Solution{
public int minKBitFlips(int[] A, int K) {
int len = A.length;
int i;
int kn = 0, revCnt = 0;
/*
* 滑动窗口算法
* 当前A[i]为0, 翻转偶数次后仍为0,需要翻转;
* 当前A[i]为1, 翻转奇数次后为0,需要翻转;
* 令翻转次数 revCnt 初始化为0,每翻转一次,
* revCnt与1做一次异或运算。翻转奇数次,revCnt为1;
* 翻转偶数次,revCnt为0。翻转0次等于翻转偶数次。
* 多做一次翻转与少做一次翻转的结果相同, 即revCnt多做
* 一次与1的异或和少做一次异或得到的结果相同
* 则当A[i] == revCnt时, A[i]需要翻转。
* 注: 没有真正的翻转元素,只记录翻转次数。
* 具体的翻转次数并不重要,只需知道是翻转奇数次
* 还是偶数次即可。
*/
for(i = 0; i < len; i++){
/*
* revCnt表示的是A[i]的翻转次数,
* 如果A[i - K]有翻转过,则revCnt多异或了一次,
* 那么应该再异或一次得到原本的revCnt。
* 注: A[i - K]翻转只会使 i - K 到 i - 1 的元素翻转,
* 而不会使A[i]翻转
*/
if(i >= K && A[i - K] > 1){
revCnt ^= 1;
A[i - K] -= 2; //复原数组,可省略
}
//在这之前, A[i]和A[i - 1]的差距仅在于A[i - K]有没有翻转
if(A[i] == revCnt){
if(i + K > len){
return -1;
}
revCnt ^= 1;
//用某种方式表示A[i]被翻转过,
//只要操作后A[i]不等于0或1就行
A[i] += 2;
++kn;
}
}
return kn;
}
}