Open In App

Flipping Bits with K-Window

Last Updated : 02 Mar, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a binary array arr[] of size n, the task is to find minimum number of operations to convert all 0s to 1s. In one operation, we can select a subarray (window) of length k and flip all its bits. If it is impossible, return -1.

Examples:

Input: arr[] = [1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1], k = 2
Output: 4
Explanation: 4 operations are required to convert all 0s to 1s:

  • Flip arr[2...3], so arr[] becomes [1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1]
  • Flip arr[4...5], so arr[] becomes [1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1]
  • Flip arr[5...6], so arr[] becomes [1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1]
  • Flip arr[6...7], so arr[] becomes [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

Input: arr[] = [0, 0, 1, 1, 1, 0, 0], k = 3
Output: -1
Explanation: It is impossible to convert all elements to 1s by performing any number of operations.

[Naive Approach] Using Nested loops - O(n*k) Space and O(1) Time

The idea is to iterate from the beginning of the array and for each index i, check if arr[i] = 0 or 1. If arr[i] = 0, then flip subarray arr[i...(i+k-1)] and increment the number of operations by 1. Since, we can only flip a subarray of size k, we will iterate i only till index (n - k - 1).

After checking all elements in subarray arr[0 ... n-k-1], if there is any element which is still 0, then it is impossible to convert all elements to 1s. Otherwise, return the number of operations.

C++
#include <iostream>
#include <vector>
using namespace std;

int kBitFlips(vector<int> &arr, int k) {
    int n = arr.size();
    int res = 0;

    for (int i = 0; i < n - k + 1; i++) {
        if (arr[i] == 0) {
            
            // if arr[i] = 0, flip arr[i...i+k-1]
            for (int j = i; j < (i + k); j++)
                arr[j] = 1 ^ arr[j];
            
            res += 1;
        }
    }

    // If arr[i] is still 0, then it is impossible
    // to convert all elements to 1
    for (int i = n - k + 1; i < n; i++) {
        if (arr[i] == 0)
            return -1;
    }

    return res;
}

int main() {
    vector<int> arr = {1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1};
    int k = 2;
    cout << kBitFlips(arr, k);
    return 0;
}
C
#include <stdio.h>

int kBitFlips(int arr[], int n, int k) {
    int res = 0;

    for (int i = 0; i < n - k + 1; i++) {
        if (arr[i] == 0) {
            
            // if arr[i] = 0, flip arr[i...i+k-1]
            for (int j = i; j < (i + k); j++)
                arr[j] = 1 ^ arr[j];
            
            res += 1;
        }
    }

    // If arr[i] is still 0, then it is impossible
    // to convert all elements to 1
    for (int i = n - k + 1; i < n; i++) {
        if (arr[i] == 0)
            return -1;
    }

    return res;
}

int main() {
    int arr[] = {1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1};
    int n = sizeof(arr) / sizeof(arr[0]);
    int k = 2;
    printf("%d", kBitFlips(arr, n, k));
    return 0;
}
Java
class GfG {
    static int kBitFlips(int[] arr, int k) {
        int n = arr.length;
        int res = 0;

        for (int i = 0; i < n - k + 1; i++) {
            if (arr[i] == 0) {

                // if arr[i] = 0, flip arr[i...i+k-1]
                for (int j = i; j < (i + k); j++)
                    arr[j] = 1 ^ arr[j];

                res += 1;
            }
        }

        // If arr[i] is still 0, then it is impossible
        // to convert all elements to 1
        for (int i = n - k + 1; i < n; i++) {
            if (arr[i] == 0)
                return -1;
        }

        return res;
    }

    public static void main(String[] args) {
        int[] arr = {1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1};
        int k = 2;
        System.out.println(kBitFlips(arr, k));
    }
}
Python
def kBitFlips(arr, k):
    n = len(arr)
    res = 0

    for i in range(n - k + 1):
        if arr[i] == 0:

            # if arr[i] = 0, flip arr[i...i+k-1]
            for j in range(i, i + k):
                arr[j] = 1 ^ arr[j]

            res += 1

    # If arr[i] is still 0, then it is impossible
    # to convert all elements to 1
    for i in range(n - k + 1, n):
        if arr[i] == 0:
            return -1

    return res

if __name__ == "__main__":
    arr = [1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]
    k = 2
    print(kBitFlips(arr, k))
C#
using System;

class GfG {
    static int kBitFlips(int[] arr, int k) {
        int n = arr.Length;
        int res = 0;

        for (int i = 0; i < n - k + 1; i++) {
            if (arr[i] == 0) {

                // if arr[i] = 0, flip arr[i...i+k-1]
                for (int j = i; j < (i + k); j++)
                    arr[j] = 1 ^ arr[j];

                res += 1;
            }
        }

        // If arr[i] is still 0, then it is impossible
        // to convert all elements to 1
        for (int i = n - k + 1; i < n; i++) {
            if (arr[i] == 0)
                return -1;
        }

        return res;
    }

    static void Main() {
        int[] arr = {1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1};
        int k = 2;
        Console.WriteLine(kBitFlips(arr, k));
    }
}
JavaScript
function kBitFlips(arr, k) {
    let n = arr.length;
    let res = 0;

    for (let i = 0; i < n - k + 1; i++) {
        if (arr[i] === 0) {

            // if arr[i] = 0, flip arr[i...i+k-1]
            for (let j = i; j < (i + k); j++) {
                arr[j] = 1 ^ arr[j];
            }

            res += 1;
        }
    }

    // If arr[i] is still 0, then it is impossible
    // to convert all elements to 1
    for (let i = n - k + 1; i < n; i++) {
        if (arr[i] === 0)
            return -1;
    }

    return res;
}

// Driver Code
let arr = [1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1];
let k = 2;
console.log(kBitFlips(arr, k));

Output
4

[Better Approach] Using Running Prefix Sum - O(n) Time and O(n) Space

The idea is to solve this problem using the prefix sum technique. The idea is to avoid flipping entire subarrays repeatedly by marking the ending indices of the flip using an auxiliary array, say flipped[]. Also, maintain a flag variable that tracks the current flip state for each element.

As we iterate through the array, if an element is 0, we check if there are k elements left to flip. If so, we flip it by toggling the flag and marking the end of flip in the flipped[] array.

C++
#include <bits/stdc++.h>
using namespace std;

int kBitFlips(vector<int> &arr, int k) {
    int n = arr.size(); 
    int res = 0, flag = 0;
    vector<int> flipped(n + 1, 0); 

    for (int i = 0; i < n; i++) {
        
        // Check if flag should be flipped at index i
        flag = (flag ^ flipped[i]);
        
        // If flag = 1, then flip the current index
        if(flag == 1)
            arr[i] ^= 1;
        
        // Finally, if arr[i] = 0, then we need to flip
        if(arr[i] == 0) {
            
            // Check if k elements are left
            if(i + k > n) 
                return -1;
            
            res += 1;
            
            // Flip flag so that upcoming elements are also flipped
            flag ^= 1;
            
            // Mark index (i + k) where flag will be flipped again
            flipped[i + k] = 1;
        }
    }

    return res; 
}

int main() {
    vector<int> arr = {1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1};
    int k = 2;
    cout << kBitFlips(arr, k);
    return 0;
}
C
#include <stdio.h>

int kBitFlips(int arr[], int n, int k) {
    int res = 0, flag = 0;
    int flipped[n + 1];
    for (int i = 0; i < n + 1; i++) 
        flipped[i] = 0;

    for (int i = 0; i < n; i++) {
        
        // Check if flag should be flipped at index i
        flag = (flag ^ flipped[i]);
        
        // If flag = 1, then flip the current index
        if (flag == 1)
            arr[i] ^= 1;
        
        // Finally, if arr[i] = 0, then we need to flip
        if (arr[i] == 0) {
            
            // Check if k elements are left
            if (i + k > n) 
                return -1;
            
            res += 1;
            
            // Flip flag so that upcoming elements are also flipped
            flag ^= 1;
            
            // Mark index (i + k) where flag will be flipped again
            flipped[i + k] = 1;
        }
    }

    return res; 
}

int main() {
    int arr[] = {1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1};
    int n = sizeof(arr) / sizeof(arr[0]);
    int k = 2;
    printf("%d", kBitFlips(arr, n, k));
    return 0;
}
Java
class GfG {
    static int kBitFlips(int[] arr, int k) {
        int n = arr.length;
        int res = 0, flag = 0;
        int[] flipped = new int[n + 1];

        for (int i = 0; i < n; i++) {
            
            // Check if flag should be flipped at index i
            flag = (flag ^ flipped[i]);
            
            // If flag = 1, then flip the current index
            if (flag == 1)
                arr[i] ^= 1;
            
            // Finally, if arr[i] = 0, then we need to flip
            if (arr[i] == 0) {
                
                // Check if k elements are left
                if (i + k > n) 
                    return -1;
                
                res += 1;
                
                // Flip flag so that upcoming elements are also flipped
                flag ^= 1;
                
                // Mark index (i + k) where flag will be flipped again
                flipped[i + k] = 1;
            }
        }

        return res; 
    }

    public static void main(String[] args) {
        int[] arr = {1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1};
        int k = 2;
        System.out.println(kBitFlips(arr, k));
    }
}
Python
def kBitFlips(arr, k):
    n = len(arr)
    res = 0
    flag = 0
    flipped = [0] * (n + 1)

    for i in range(n):
        
        # Check if flag should be flipped at index i
        flag ^= flipped[i]
        
        # If flag = 1, then flip the current index
        if flag == 1:
            arr[i] ^= 1
        
        # Finally, if arr[i] = 0, then we need to flip
        if arr[i] == 0:
            
            # Check if k elements are left
            if i + k > n:
                return -1
            
            res += 1
            
            # Flip flag so that upcoming elements are also flipped
            flag ^= 1
            
            # Mark index (i + k) where flag will be flipped again
            flipped[i + k] = 1

    return res 

if __name__ == "__main__":
    arr = [1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]
    k = 2
    print(kBitFlips(arr, k))
C#
using System;

class GfG {
    static int kBitFlips(int[] arr, int k) {
        int n = arr.Length;
        int res = 0, flag = 0;
        int[] flipped = new int[n + 1];

        for (int i = 0; i < n; i++) {
            
            // Check if flag should be flipped at index i
            flag ^= flipped[i];
            
            // If flag = 1, then flip the current index
            if (flag == 1)
                arr[i] ^= 1;
            
            // Finally, if arr[i] = 0, then we need to flip
            if (arr[i] == 0) {
                
                // Check if k elements are left
                if (i + k > n) 
                    return -1;
                
                res += 1;
                
                // Flip flag so that upcoming elements are also flipped
                flag ^= 1;
                
                // Mark index (i + k) where flag will be flipped again
                flipped[i + k] = 1;
            }
        }

        return res; 
    }

    static void Main() {
        int[] arr = {1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1};
        int k = 2;
        Console.WriteLine(kBitFlips(arr, k));
    }
}
JavaScript
function kBitFlips(arr, k) {
    let n = arr.length;
    let res = 0;
    let flag = 0;
    let flipped = new Array(n + 1).fill(0);

    for (let i = 0; i < n; i++) {
        
        // Check if flag should be flipped at index i
        flag ^= flipped[i];
        
        // If flag = 1, then flip the current index
        if (flag == 1)
            arr[i] ^= 1;
        
        // Finally, if arr[i] = 0, then we need to flip
        if (arr[i] == 0) {
            
            // Check if k elements are left
            if (i + k > n)
                return -1;
            
            res += 1;
            
            // Flip flag so that upcoming elements are also flipped
            flag ^= 1;
            
            // Mark index (i + k) where flag will be flipped again
            flipped[i + k] = 1;
        }
    }

    return res; 
}

// Driver Code
let arr = [1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1];
let k = 2;
console.log(kBitFlips(arr, k));

Output
4

[Expected Approach] Using Queue - O(n) Time and O(k) Space

We can further optimize the previous approach by using a queue instead of an auxiliary array. As we iterate through the array, we maintain a flag to determine whether the current element has been flipped or not. Queue is used to track flips within the current window of size k.

For each element, if it has been flipped (i.e., flag == 1), we flip it back to its original state. When encountering a 0, we check if a flip of size k is possible. If so, we flip the current element by toggling the flag, increment the flip count, and push a 1 into the queue to mark the start of the flip. If we encounter a 1, we push a 0 into the queue.

C++
#include <bits/stdc++.h>
using namespace std;

int kBitFlips(vector<int> &arr, int k) {
    int n = arr.size(); 
    int res = 0, flag = 0;
    queue<int> q; 

    for (int i = 0; i < n; i++) {
        
        if(i >= k) {
            flag ^= q.front();
            q.pop();
        }
        
        // If flag = 1, then flip the current index
        if(flag == 1)
            arr[i] ^= 1;
        
        // Finally, if arr[i] = 0, then we need to flip
        if(arr[i] == 0) {
            
            // Check if k elements are left
            if(i + k > n) 
                return -1;
            
            res += 1;
            
            // Flip flag so that upcoming elements are also flipped
            flag ^= 1;
            
            // If we flip, push 1 to the queue
            q.push(1);
        }
        else {
            
            // If we don't flip, push 0 to queue
            q.push(0);
        }
    }

    return res; 
}

int main() {
    vector<int> arr = {1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1};
    int k = 2;
    cout << kBitFlips(arr, k);
    return 0;
}
Java
import java.util.LinkedList;
import java.util.Queue;

class GfG {
    static int kBitFlips(int[] arr, int k) {
        int n = arr.length; 
        int res = 0, flag = 0;
        Queue<Integer> q = new LinkedList<>(); 

        for (int i = 0; i < n; i++) {
            
            if(i >= k)
                flag ^= q.poll();
            
            // If flag = 1, then flip the current index
            if(flag == 1)
                arr[i] ^= 1;
            
            // Finally, if arr[i] = 0, then we need to flip
            if(arr[i] == 0) {
                
                // Check if k elements are left
                if(i + k > n) 
                    return -1;
                
                res += 1;
                
                // Flip flag so that upcoming elements are also flipped
                flag ^= 1;
                
                // If we flip, push 1 to the queue
                q.offer(1);
            }
            else {
                
                // If we don't flip, push 0 to queue
                q.offer(0);
            }
        }

        return res; 
    }

    public static void main(String[] args) {
        int[] arr = {1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1};
        int k = 2;
        System.out.println(kBitFlips(arr, k));
    }
}
Python
from collections import deque

def kBitFlips(arr, k):
    n = len(arr)
    res = 0
    flag = 0
    q = deque()

    for i in range(n):
        if i >= k:
            flag ^= q.popleft()

        # If flag = 1, then flip the current index
        if flag == 1:
            arr[i] ^= 1

        # Finally, if arr[i] = 0, then we need to flip
        if arr[i] == 0:
            
            # Check if k elements are left
            if i + k > n:
                return -1

            res += 1
            
            # Flip flag so that upcoming elements are also flipped
            flag ^= 1
            
            # If we flip, push 1 to the queue
            q.append(1)
        else:
            
            # If we don't flip, push 0 to queue
            q.append(0)

    return res

if __name__ == "__main__":
    arr = [1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]
    k = 2
    print(kBitFlips(arr, k))
C#
using System;
using System.Collections.Generic;

class GfG {
    static int KBitFlips(int[] arr, int k) {
        int n = arr.Length; 
        int res = 0, flag = 0;
        Queue<int> q = new Queue<int>();

        for (int i = 0; i < n; i++) {
            if (i >= k) {
                flag ^= q.Dequeue();
            }

            // If flag = 1, then flip the current index
            if (flag == 1)
                arr[i] ^= 1;

            // Finally, if arr[i] = 0, then we need to flip
            if (arr[i] == 0) {
                // Check if k elements are left
                if (i + k > n)
                    return -1;

                res += 1;

                // Flip flag so that upcoming elements are also flipped
                flag ^= 1;

                // If we flip, push 1 to the queue
                q.Enqueue(1);
            } else {
                
                // If we don't flip, push 0 to queue
                q.Enqueue(0);
            }
        }

        return res;
    }

    static void Main() {
        int[] arr = {1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1};
        int k = 2;
        Console.WriteLine(KBitFlips(arr, k));
    }
}
JavaScript
function kBitFlips(arr, k) {
    let n = arr.length;
    let res = 0, flag = 0;
    let q = [];

    for (let i = 0; i < n; i++) {
        if (i >= k) {
            flag ^= q.shift();
        }

        // If flag = 1, then flip the current index
        if (flag === 1)
            arr[i] ^= 1;

        // Finally, if arr[i] = 0, then we need to flip
        if (arr[i] === 0) {
            // Check if k elements are left
            if (i + k > n)
                return -1;

            res += 1;

            // Flip flag so that upcoming elements are also flipped
            flag ^= 1;

            // If we flip, push 1 to the queue
            q.push(1);
        } else {
            // If we don't flip, push 0 to queue
            q.push(0);
        }
    }

    return res;
}

// Driver Code
let arr = [1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1];
let k = 2;
console.log(kBitFlips(arr, k));

Output
4

Article Tags :
Practice Tags :

Similar Reads