Given a binary array a[] and a number k, we need to find length of the longest subsegment of '1's possible by changing at most k '0's.
Examples:
Input : a[] = {1, 0, 0, 1, 1, 0, 1},
k = 1.
Output : 4
Explanation : Here, we should only change 1
zero(0). Maximum possible length we can get
is by changing the 3rd zero in the array,
we get a[] = {1, 0, 0, 1, 1, 1, 1}
Input : a[] = {1, 0, 0, 1, 0, 1, 0, 1, 0, 1},
k = 2.
Output : 5
Output: Here, we can change only 2 zeros.
Maximum possible length we can get is by
changing the 3rd and 4th (or) 4th and 5th
zeros.
We can solve this problem using two pointers technique. Let us take a subarray [l, r] which contains at most k zeroes. Let our left pointer be l and right pointer be r. We always maintain our subsegment [l, r] to contain no more than k zeroes by moving the left pointer l. Check at every step for maximum size (i.e, r-l+1).
// CPP program to find length of longest
// subsegment of all 1's by changing at
// most k 0's
#include <iostream>
using namespace std;
int longestSubSeg(int a[], int n, int k)
{
int cnt0 = 0;
int l = 0;
int max_len = 0;
// i decides current ending point
for (int i = 0; i < n; i++) {
if (a[i] == 0)
cnt0++;
// If there are more 0's move
// left point for current ending
// point.
while (cnt0 > k) {
if (a[l] == 0)
cnt0--;
l++;
}
max_len = max(max_len, i - l + 1);
}
return max_len;
}
// Driver code
int main()
{
int a[] = { 1, 0, 0, 1, 0, 1, 0, 1 };
int k = 2;
int n = sizeof(a) / sizeof(a[0]);
cout << longestSubSeg(a, n, k);
return 0;
}
// Java program to find length of
// longest subsegment of all 1's
// by changing at most k 0's
import java.io.*;
class GFG {
static int longestSubSeg(int a[], int n,
int k)
{
int cnt0 = 0;
int l = 0;
int max_len = 0;
// i decides current ending point
for (int i = 0; i < n; i++) {
if (a[i] == 0)
cnt0++;
// If there are more 0's move
// left point for current ending
// point.
while (cnt0 > k) {
if (a[l] == 0)
cnt0--;
l++;
}
max_len = Math.max(max_len, i - l + 1);
}
return max_len;
}
// Driver code
public static void main (String[] args)
{
int a[] = { 1, 0, 0, 1, 0, 1, 0, 1 };
int k = 2;
int n = a.length;
System.out.println( longestSubSeg(a, n, k));
}
}
// This code is contributed by vt_m
# Python3 program to find length
# of longest subsegment of all 1's
# by changing at most k 0's
def longestSubSeg(a, n, k):
cnt0 = 0
l = 0
max_len = 0;
# i decides current ending point
for i in range(0, n):
if a[i] == 0:
cnt0 += 1
# If there are more 0's move
# left point for current
# ending point.
while (cnt0 > k):
if a[l] == 0:
cnt0 -= 1
l += 1
max_len = max(max_len, i - l + 1);
return max_len
# Driver code
a = [1, 0, 0, 1, 0, 1, 0, 1 ]
k = 2
n = len(a)
print(longestSubSeg(a, n, k))
# This code is contributed by Smitha Dinesh Semwal
// C# program to find length of
// longest subsegment of all 1's
// by changing at most k 0's
using System;
class GFG {
static int longestSubSeg(int[] a, int n,
int k)
{
int cnt0 = 0;
int l = 0;
int max_len = 0;
// i decides current ending point
for (int i = 0; i < n; i++)
{
if (a[i] == 0)
cnt0++;
// If there are more 0's move
// left point for current ending
// point.
while (cnt0 > k) {
if (a[l] == 0)
cnt0--;
l++;
}
max_len = Math.Max(max_len, i - l + 1);
}
return max_len;
}
// Driver code
public static void Main()
{
int[] a = { 1, 0, 0, 1, 0, 1, 0, 1 };
int k = 2;
int n = a.Length;
Console.WriteLine(longestSubSeg(a, n, k));
}
}
// This code is contributed by vt_m
<?php
// PHP program to find length of longest
// subsegment of all 1's by changing at
// most k 0's
function longestSubSeg( $a, $n, $k)
{
$cnt0 = 0;
$l = 0;
$max_len = 0;
// i decides current ending point
for($i = 0; $i < $n; $i++)
{
if ($a[$i] == 0)
$cnt0++;
// If there are more 0's move
// left point for current ending
// point.
while ($cnt0 > $k)
{
if ($a[$l] == 0)
$cnt0--;
$l++;
}
$max_len = max($max_len, $i - $l + 1);
}
return $max_len;
}
// Driver code
$a = array(1, 0, 0, 1, 0, 1, 0, 1);
$k = 2;
$n = count($a);
echo longestSubSeg($a, $n, $k);
// This code is contributed by anuj_67.
?>
<script>
// JavaScript program to find length of
// longest subsegment of all 1's
// by changing at most k 0's
function longestSubSeg(a, n, k)
{
let cnt0 = 0;
let l = 0;
let max_len = 0;
// i decides current ending point
for (let i = 0; i < n; i++)
{
if (a[i] == 0)
cnt0++;
// If there are more 0's move
// left point for current ending
// point.
while (cnt0 > k) {
if (a[l] == 0)
cnt0--;
l++;
}
max_len = Math.max(max_len, i - l + 1);
}
return max_len;
}
let a = [ 1, 0, 0, 1, 0, 1, 0, 1 ];
let k = 2;
let n = a.length;
document.write(longestSubSeg(a, n, k));
</script>
Output
5
There is another O(n) approach, where we can keep a track of number of 1s will be discarded if a 0 is not converted to one.
As we move right and encounter more 0s that what is permitted, we reduce one 0 to the left and at that time we reduce the count of ones by the 1s adjacent to the left-most zero being discarded.
#include <bits/stdc++.h>
using namespace std;
int solve(int binaryList[],int n, int conversionLimit)
{
vector<int> listOfOnesCovered;
int oneCount = 0;
for (int i = 0; i < n; i++)
{
int number = binaryList[i];
if (number == 0)
{
listOfOnesCovered.push_back(
oneCount > 0 ? oneCount + 1 : 1);
oneCount = 0;
}
else
{
++oneCount;
}
}
int totalOnes = 0;
int maxOnes = 0;
int zeroCount = 0;
for (int i = 0; i < n; i++)
{
int integer = binaryList[i];
++totalOnes;
if (integer == 0)
{
if (zeroCount >= conversionLimit)
{
totalOnes -= listOfOnesCovered[zeroCount - conversionLimit];
}
++zeroCount;
}
maxOnes = max(totalOnes, maxOnes);
}
return maxOnes;
}
int main()
{
// Code
int binaryList[] = {1, 0, 0, 0, 0, 1, 1, 1};
int n = sizeof(binaryList) / sizeof(binaryList[0]);
int conversionLimit = 2;
cout << solve(binaryList,n, conversionLimit) << endl;
}
// This code is contributed by akashish__.
/*package whatever //do not write package name here */
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class Solution {
public int solve(int[] binaryList, int conversionLimit) {
List<Integer> listOfOnesCovered = new ArrayList<>();
int oneCount = 0;
for (int number : binaryList) {
if (number == 0) {
listOfOnesCovered.add(oneCount > 0 ? oneCount + 1 : 1);
oneCount = 0;
} else {
++oneCount;
}
}
int totalOnes = 0;
int maxOnes = 0;
int zeroCount = 0;
for (int integer : binaryList) {
++totalOnes;
if (integer == 0) {
if (zeroCount >= conversionLimit) {
totalOnes -= listOfOnesCovered.get(zeroCount - conversionLimit);
}
++zeroCount;
}
maxOnes = Math.max(totalOnes, maxOnes);
}
return maxOnes;
}
public static void main (String[] args){
System.out.println(
new Solution().solve(new int[]{1, 0, 0, 0, 0,1,1, 1}, 2)
);
}
}
import math
class Solution :
def solve(self, binaryList, conversionLimit) :
listOfOnesCovered = []
oneCount = 0
for number in binaryList :
if (number == 0) :
listOfOnesCovered.append(oneCount + 1 if oneCount > 0 else 1)
oneCount = 0
else :
oneCount += 1
totalOnes = 0
maxOnes = 0
zeroCount = 0
for integer in binaryList :
totalOnes += 1
if (integer == 0) :
if (zeroCount >= conversionLimit) :
totalOnes -= listOfOnesCovered[zeroCount - conversionLimit]
zeroCount += 1
maxOnes = max(totalOnes,maxOnes)
return maxOnes
@staticmethod
def main( args) :
print(Solution().solve([1, 0, 0, 0, 0, 1, 1, 1], 2))
if __name__=="__main__":
Solution.main([])
# This code is contributed by aadityaburujwale.
// C# code for the above approach
using System;
using System.Collections;
public class Solution {
public int solve(int[] binaryList, int conversionLimit)
{
ArrayList listOfOnesCovered = new ArrayList();
int oneCount = 0;
foreach(int number in binaryList)
{
if (number == 0) {
listOfOnesCovered.Add(
oneCount > 0 ? oneCount + 1 : 1);
oneCount = 0;
}
else {
++oneCount;
}
}
int totalOnes = 0;
int maxOnes = 0;
int zeroCount = 0;
foreach(int integer in binaryList)
{
++totalOnes;
if (integer == 0) {
if (zeroCount >= conversionLimit) {
totalOnes -= (int)listOfOnesCovered
[zeroCount - conversionLimit];
}
++zeroCount;
}
maxOnes = Math.Max(totalOnes, maxOnes);
}
return maxOnes;
}
static public void Main()
{
// Code
Solution s = new Solution();
Console.WriteLine(s.solve(
new int[] { 1, 0, 0, 0, 0, 1, 1, 1 }, 2));
}
}
// This code is contributed by lokeshmvs21.
const solve = (binaryList, n, conversionLimit) => {
const listOfOnesCovered = [];
let oneCount = 0;
for (let i = 0; i < n; i++) {
const number = binaryList[i];
if (number === 0) {
listOfOnesCovered.push(oneCount > 0 ? oneCount + 1 : 1);
oneCount = 0;
} else {
oneCount++;
}
}
let totalOnes = 0;
let maxOnes = 0;
let zeroCount = 0;
for (let i = 0; i < n; i++) {
const integer = binaryList[i];
totalOnes++;
if (integer === 0) {
if (zeroCount >= conversionLimit) {
totalOnes -= listOfOnesCovered[zeroCount - conversionLimit];
}
zeroCount++;
}
maxOnes = Math.max(totalOnes, maxOnes);
}
return maxOnes;
};
const binaryList = [1, 0, 0, 0, 0, 1, 1, 1];
const n = binaryList.length;
const conversionLimit = 2;
console.log(solve(binaryList, n, conversionLimit));
// This code is contributed by akashish__
Output
5
Time complexity: O(n), where n is the length of the binary list. We traverse the binary list twice, and each traversal takes O(n) time.
Space complexity: O(n), where n is the length of the binary list. We use an additional vector of size n to store the number of ones covered.