995. Minimum Number of K Consecutive Bit Flips


Problem Explanation

Given an array / list which contains only binary digits, (1s and 0s), we want to perform a K-bit flip operation in the list. A K-bit flip operation involves choosing a subarray or sublist of length K and simultaneously changing all 0s in the subarray to 1, and all the 1s in the subarray to 0.

The task is to find the minimum number of K-bit flips required to make all the numbers in the array / list as 1. If it is impossible to do so, we should return -1.

For example, if our array is [0,1,0] and K equals 1, the minimum number of 1-bit flips needed to make all the array elements 1 is 2 (flip 0 at index 0, and 0 at index 2).

Approach

This problem can be solved using a simple technique of flipping the subarrays. We traverse the array one by one and look ahead of the k-length subarray which needs to be flipped. We flip the 1s and 0s if found in the current k-length subarray and keep track of the total number of flips, to be returned as the result. One boundary condition to be kept in mind is whether the flip operation is feasible or not i.e. if the remaining length of the array is less than k, then flipping a k-length subarray is not possible, return -1.

Let’s walk through an example. Take the array [0,1,0,1,0] and let K be 1. At index 0, we flip the bit from 0 to 1 and record the flip. We do the same at indices 2 and 4. At the end, our array is fully converted to 1s and we have done three 1-bit flips in total.

Python Solution

1
2python
3class Solution:
4    def minKBitFlips(self, A, K):
5        n = len(A)
6        flip = ans = 0
7        is_flip = [0] * n
8        for i in range(n):
9            if i >= K and A[i - K] == 2: 
10                flip -= is_flip[i - K]
11            if flip % 2 == A[i]:
12                if i + K > n: 
13                    return -1
14                A[i] = 2
15                is_flip[i] = 1
16                flip += 1
17            ans += is_flip[i]
18        return ans

Java Solution

1
2java
3class Solution {
4    public int minKBitFlips(int[] A, int K) {
5        int n = A.length;
6        int[] flip = new int[n];
7        int ans = 0, revCnt = 0;
8        for (int i = 0; i < n; ++i) {
9            if (i >= K) {
10                revCnt ^= flip[i - K];
11            }
12            if (revCnt % 2 == A[i]) {
13                if (i + K > n) {
14                    return -1;
15                }
16                flip[i] = 1;
17                revCnt ^= 1;
18                ++ans;
19            }
20        }
21        return ans;
22    }
23}

JavaScript Solution

1
2javascript
3var minKBitFlips = function(A, K) {
4    let flip = 0, res = 0, arr = new Array(A.length).fill(0);
5    for(let i=0;i<A.length;i++) {
6        if(i>=K) flip^=arr[i-K];
7        if(flip%2===A[i]) {
8            if(i+K>A.length) return -1;
9            flip^=1;
10            arr[i]=1;
11            res++;
12        }
13    }
14    return res;
15};

C++ Solution

1
2cpp
3class Solution {
4public:
5    int minKBitFlips(vector<int>& A, int K) {
6        vector<int> flip(A.size());
7        int flipped = 0;
8        int res = 0;
9        for(int i = 0; i < A.size(); ++i){
10            if(i >= K)
11                flipped ^= flip[i-K];
12            if(flipped%A[i] == 0){
13                if(i+K > A.size())
14                    return -1;
15                flipped ^= 1;
16                ++res;
17                flip[i] = 1;
18            }
19        }
20        return res;
21    }
22};

C# Solution

1
2csharp
3public class Solution {
4    public int MinKBitFlips(int[] A, int K) {
5        int flips=0, result=0,n=A.Length;
6        int[] isFlipped=new int[n];
7        for(int i=0;i<n;i++){
8            if(i>=K)
9                flips^=isFlipped[i-K];
10            if(flips%2==A[i]){
11                if(i+K>n)
12                    return -1;
13                isFlipped[i]=1;
14                flips^=1;
15                result++;
16            }
17        }
18        return result;
19    }
20}

Solution Explanation

Taking a look at the implementations in various languages, we can deduce that all solutions follow a similar approach.

Firstly, an auxiliary array (flip[] or is_flip[]) of the same length as the input array / list is initialized. This array is used to keep track of which indices of the input array / list have been flipped.

Next, the input array / list is iterated over. For each index, if it lies beyond the Kth position, it's checked whether the element at the current index minus K, was flipped or not. If it was, the flip count is decreased.

Then, the current number of flips performed is checked against the number at the current index. If they are equal, the solution checks whether there are enough elements beyond the current index to flip K bits. If not, -1 is returned indicating that no solution exists. Else, the current index is marked as flipped, the flip count is incremented and the number of flips performed is increased.

Finally, after the traversal is done, the total number of flips performed is returned.

In these solutions, the time complexity is O(N) where N is the length of the array / list A. This happens because each index of the array / list is explored once. The space complexity is also O(N) as an additional array / list of size N is used to keep track of flips.

This problem can serve as a good practice for understanding bit manipulation, array / list management and problem-solving using a greedy algorithm.


Got a question? Ask the Teaching Assistant anything you don't understand.

Still not clear? Ask in the Forum,  Discord or Submit the part you don't understand to our editors.


TA 👨‍🏫