Given a binary array arr[], 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.
Table of Content
[Naive Approach] Using Nested loops - O(n*k) Time and O(1) Space
We scan the array from left to right, and whenever we see a 0, we flip the next k elements so that this 0 becomes 1. We keep doing this until we reach the last possible starting position. If at the end any 0 remains, it means it is impossible to make all elements 1; otherwise, the number of flips we made is the answer.
Working:
- Start iterating from index 0.
- Whenever you find arr[i] == 0, flip the next k elements by XOR with 1.
-> This ensures the current 0 becomes 1. - Keep a counter (res) to track the number of flips performed.
- At the end, check the last (k - 1) elements. If any of them is 0, return -1 (not possible).Otherwise, return the total flips.
#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;
}
#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;
}
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));
}
}
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))
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));
}
}
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
Instead of actually flipping k elements every time we see a 0, we use a prefix sum like trick. We maintain a flag that tells whether the current index is flipped or not, and an auxiliary flipped[] array to mark where a flip ends. This way, we avoid re-flipping the same subarray repeatedly.
Working:
- Maintain a flag variable to indicate whether the current position is flipped or not.
- Maintain an auxiliary array flipped[] where flipped[i] = 1 means a flip effect ends at index i.
- Traverse the array from left to right:
-> Update flag using flipped[i] (to cancel earlier flips).
-> If flag == 1, toggle arr[i] (since this index is flipped). - If after considering flips, arr[i] == 0:
-> Check if there are at least k elements left. If not, return -1.
-> Increment the flip count (res).
-> Toggle flag to apply a flip starting here.
-> Mark flipped[i + k] = 1 to cancel this flip after k steps. - After the loop ends, return res as the minimum number of flips needed.
#include <iostream>
#include<vector>
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;
}
#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;
}
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));
}
}
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))
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));
}
}
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
Instead of keeping a whole auxiliary array to mark flip boundaries, we use a queue of size at most k to track active flips. The flag variable tells whether the current element is in a flipped state. When we encounter a 0, we start a new flip of size k and mark it in the queue; when we move past that window, we remove its effect from the flag.
Working:
- Start with res = 0 (flip count), flag = 0 (tracks if current bit is flipped), and an empty queue q.
- For each index i in the array:
->If i >= k, remove the effect of the flip that started k steps ago (flag ^= q.front(); q.pop();).
->If flag == 1, flip the current element (arr[i] ^= 1).
->If arr[i] == 0, check if k elements remain; if not return -1, else increment res, toggle flag, and push 1 into q.else push 0 into q - After processing all elements, return res as the minimum flips.
#include <iostream>
#include<vector>
#include<queue>
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;
}
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));
}
}
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))
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));
}
}
// Node class
class Node {
constructor(data) {
this.data = data;
this.next = null;
}
}
// Custom Queue class
class Queue {
constructor() {
this.front = this.rear = null;
this.size = 0;
}
isEmpty() {
return this.size === 0;
}
enqueue(data) {
const node = new Node(data);
if (this.isEmpty()) {
this.front = this.rear = node;
} else {
this.rear.next = node;
this.rear = node;
}
this.size++;
}
dequeue() {
if (this.isEmpty()) return null;
const val = this.front.data;
this.front = this.front.next;
if (!this.front) this.rear = null;
this.size--;
return val;
}
}
function kBitFlips(arr, k) {
let n = arr.length;
let res = 0, flag = 0;
let q = new Queue();
for (let i = 0; i < n; i++) {
if (i >= k) {
let val = q.dequeue();
if (val !== null) flag ^= val;
}
// If flag = 1, flip the current index
if (flag === 1)
arr[i] ^= 1;
if (arr[i] === 0) {
if (i + k > n) return -1;
res += 1;
flag ^= 1;
// flipped
q.enqueue(1);
} else {
// not flipped
q.enqueue(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