在仅包含 0
和 1
的数组 A
中,一次 K
位翻转包括选择一个长度为 K
的(连续)子数组,同时将子数组中的每个 0
更改为 1
,而每个 1
更改为 0
。
返回所需的 K
位翻转的最小次数,以便数组没有值为 0
的元素。如果不可能,返回 -1
。
示例 1:
输入:A = [0,1,0], K = 1
输出:2
解释:先翻转 A[0],然后翻转 A[2]。
示例 2:
输入:A = [1,1,0], K = 2
输出:-1
解释:无论我们怎样翻转大小为 2 的子数组,我们都不能使数组变为 [1,1,1]。
示例 3:
输入:A = [0,0,0,1,0,1,1,0], K = 3
输出:3
解释:
翻转 A[0],A[1],A[2]: A变成 [1,1,1,1,0,1,1,0]
翻转 A[4],A[5],A[6]: A变成 [1,1,1,1,1,0,0,0]
翻转 A[5],A[6],A[7]: A变成 [1,1,1,1,1,1,1,1]
提示:
1 <= A.length <= 30000
1 <= K <= A.length
解答
贪心,从左至右遍历,只要遇到0
就把该位置及其后面的相应K-1
个元素翻转,复杂度为o(nk)
,可惜超时了。
class Solution {
public:
int minKBitFlips(vector<int>& A, int K) {
if(A.size() < 1)
return 0;
int i = 0;
int result = 0;
for(; i < A.size() - K + 1; i++){
if(A[i] == 0){
A[i] = 1;
result++;
for(int j = 1; j < K; j++){
A[i + j] = 1 - A[i + j];
}
}
}
for(; i < A.size(); i++){
if(A[i] == 0)
return -1;
}
return result;
}
};
实际上,我们并不需要真的逐个把元素翻转,使用一个差分数组记录相邻元素翻转次数之差,即diff[i]
表示A[i-1]
和A[i]
翻转次数的差值。reverseCount
记录当前遍历到的元素的总翻转次数,因此若总翻转次数与A[i]
的奇偶性相反(两者之和为奇数),则表示当前元素已经翻转成1
,否则需要增加一次翻转次数。参考官方题解,由于全程只需要记录翻转次数的奇偶性,因此,可以采用位运算进行加速。
class Solution {
public:
int minKBitFlips(vector<int>& A, int K) {
int n = A.size();
int result = 0;
int reverseCount = 0;
vector<int> diff(n + 1, 0);
for(int i = 0; i < n; i++){
reverseCount += diff[i];
// reverseCount ^= diff[i];
// if(reverseCount ^ A[i] == 0)
if(!((reverseCount + A[i]) & 1))
{
if(i > n - K){
return -1;
}
result++;
// reverseCount ^= 1;
// diff[i + K] ^= 1;
reverseCount += 1;
diff[i + K] -= 1;
}
}
return result;
}
};
下面为官方题解中进一步降低空间复杂度的解法,复用数组A
来记录相应是否进行了翻转,若翻转,则将相应元素加2.同样按照从左到有遍历的思路,若遍历到A[i]
时,发现A[i-K]>1
,则表示该元素相较于上一窗口少执行了一次翻转操作,将reverseCount
奇偶性反转,其余操作与上述解法一致。
class Solution {
public:
int minKBitFlips(vector<int> &A, int K) {
int n = A.size();
int ans = 0, revCnt = 0;
for (int i = 0; i < n; ++i) {
if (i >= K && A[i - K] > 1) {
revCnt ^= 1;
A[i - K] -= 2; // 复原数组元素,若允许修改数组 A,则可以省略
}
if (A[i] == revCnt) {
if (i + K > n) {
return -1;
}
++ans;
revCnt ^= 1;
A[i] += 2;
}
}
return ans;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/minimum-number-of-k-consecutive-bit-flips/solution/k-lian-xu-wei-de-zui-xiao-fan-zhuan-ci-s-bikk/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。