题目
在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 0。
返回所需的 K 位翻转的最小次数,以便数组没有值为 0 的元素。如果不可能,返回 -1。
示例
输入:A = [0,1,0], K = 1
输出:2
解释:先翻转 A[0],然后翻转 A[2]。
提示
- 1 <= A.length <= 30000
- 1 <= K <= A.length
题解
- 维持一个大小为K的窗口,左指针为0就反转并更新反转次数,,最后判断左指针到数组末尾是否包含0,若包含返回-1,否则返回反转次数
(超时)
- 如何优化?
- 对于每一个大小为K的窗口,我们只需要判断该窗口的第一个元素是否为0,若为0就反转,否则就不反转
- 对于窗口内每一个元素,记录其之前的反转次数总和,并结合当前元素判断以该元素为首的窗口是否需要反转
- 反转次数为偶数情况下,元素不变,反转次数为奇数情况下,更换该元素的值
参考代码
class Solution {
public int minKBitFlips(int[] A, int K) {
int len = A.length;
int[] diff = new int[len + 1]; // 两个相邻元素反转次数差值
int res = 0;
int count = 0;
for(int i = 0; i < len; i++) {
count += diff[i]; // 统计当前元素的反转次数
// 反转次数+当前值若为偶数,表示A[i]为0,反转该窗口
if((count + A[i]) % 2 == 0) {
if(i + K > len) return -1;
res++; // 更新反转次数
// 差分数组若区间[i, i+K-1]反转了一次,则count++,diff[i+K]--
count++; // 更新
diff[i+K]--; // 更新
}
}
return res;
}
}