Open In App

Maximize sum of assigned weights by flipping at most K bits in given Binary String

Improve
Improve
Like Article
Like
Save
Share
Report

Given a binary string str of length N and an integer K, the task is to find the maximum possible sum of assigned weights that can be obtained by flipping at most K bits in the given binary string. The weight assigned to the characters of this string are as follows:

  • If a character is ‘0’, then the weight is 0.
  • If a character is ‘1’ and the character preceding it is also ‘1’, then the weight is 2.
  • If a character is ‘1’ and there is no character before it or the character preceding it is ‘0’, then the weight is 1.

Examples:

Input: str = “10100”, K = 2
Output: 7
Explanation:
1st flip: Flip the character at index 1, the string becomes “11100”.
2nd flip: Flip the character at index 3, the string becomes “11110”.
The weight of the resulting string is 1 + 2 + 2 + 2 + 0 = 7, which is maximum.

Input: str = “100101”, K = 1
Output: 6
Explanation:
1st flip: Flip the character at index 5, the string becomes “100111”.
The weight of the resulting string is 1 + 0 + 0 + 1 + 2 + 2 = 6, which is maximum.

Approach: The weight of character ‘1’ appearing after a ‘1’ is greatest among all characters, so to maximize the sum, try to create as many such 1s possible. The segments of 0s to be flipped to 1 can be prioritized as follows:

  • First priority: Flip all 0s enclosed between two 1s, this would increase the weight of the segment of form 10…01 by (2*(number of 0s enclosed) + 1). If x is greater than or equal to the number of 0s enclosed otherwise by 2*(number of 0s enclosed).
  • Second priority” Flip 0s at the beginning of the string preceding the first occurrence of 1s in the string, this would increase the weight of segment of form 0…01 by 2*(number of flipped 0s).
  • Third priority: Flip 0s at the end of the string succeeding the last occurrence of 1 in the string, this would increase the weight of the segment of form 10…0 by 2*(number of flipped 0s).

Flip the character of the given string as per the above priority to maximize the weight and then find the weight of the resulting string after at most K flips. 

Below is the implementation of this approach:

C++




// C++ program of the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find maximum sum of
// weights of binary string after
// at most K flips
int findMax(string s, int n, int k)
{
    int ans = 0;
 
    // Stores lengths of substrings
    // of the form 1..00..1s
    int l = 0;
 
    // Stores the index of last 1
    // encountered in the string
    int ind = -1;
 
    // Stores the index of first 1
    // encountered
    int indf = -1;
 
    // Stores lengths of all substrings
    // having of 0s enclosed by 1s
    // at both ends
    multiset<int> ls;
 
    // Traverse the string
    for (int i = 0; i < n; i++) {
        // If character is 0
        if (s[i] == '0')
            l++;
 
        // If character is 1
        // First Priority
        else if (s[i] == '1'
                 && l > 0 && ans != 0) {
            ls.insert(l);
            l = 0;
        }
 
        // Second Priority
        if (s[i] == '1') {
            ind = i;
            l = 0;
            if (indf == -1)
                indf = i;
 
            // Add according to the
            // first priority
            if (i > 0 && s[i - 1] == '1')
                ans += 2;
            else
                ans += 1;
        }
    }
 
    // Stores length of the shortest
    // substring of 0s
    int curr;
 
    // Convert shortest substrings
    // of 0s to 1s
    while (k > 0 && !ls.empty()) {
        curr = *ls.begin();
 
        // Add according to the
        // first priority
        if (k >= curr) {
            ans += (2 * curr + 1);
            k -= curr;
        }
 
        // Add according to the
        // third priority
        else {
            ans += (2 * k);
            k = 0;
        }
        ls.erase(ls.begin());
    }
 
    // If more 0s can be made into 1,
    // then check for 0s at ends
    if (k > 0) {
        // Update the ans
        ans += (2 * min(k,
                        n - (ind + 1))
                - 1);
        k -= min(k, n - (ind + 1));
 
        if (ind > -1)
            ans++;
    }
 
    // If K is non-zero, then flip 0s
    // at the beginning
    if (k > 0) {
        ans += (min(indf, k) * 2 - 1);
 
        if (indf > -1)
            ans++;
    }
 
    // Return the final weights
    return ans;
}
 
// Driver Code
int main()
{
    // Given string str
    string str = "1110000101";
 
    int N = str.length();
 
    // Given K flips
    int K = 3;
 
    // Function Call
    cout << findMax(str, N, K);
 
    return 0;
}


Java




// Java program of the above approach
import java.util.*;
 
class GFG
{
 
  // Function to find maximum sum of
  // weights of binary String after
  // at most K flips
  static int findMax(String s, int n, int k)
  {
    var ans = 0;
 
    // Stores lengths of subStrings
    // of the form 1..00..1s
    var l = 0;
 
    // Stores the index of last 1
    // ensize()ered in the String
    var ind = -1;
 
    // Stores the index of first 1
    // ensize()ered
    var indf = -1;
 
    // Stores lengths of all subStrings
    // having of 0s enclosed by 1s
    // at both ends
    var ls = new TreeSet<Integer>();
 
    // Traverse the String
    for (var i = 0; i < n; i++) {
      // If character is 0
      if (s.charAt(i) == '0')
        l += 1;
 
      // If character is 1
      // First Priority
      else if ((s.charAt(i) == '1') && (l > 0)
               && (ans != 0)) {
        ls.add(l);
        l = 0;
      }
      // Second Priority
      if (s.charAt(i) == '1') {
        ind = i;
        l = 0;
        if (indf == -1)
          indf = i;
 
        // add according to the
        // first priority
        if ((i > 0) && (s.charAt(i - 1) == '1'))
          ans += 2;
        else
          ans += 1;
      }
    }
 
    // Stores length of the shortest
    // subString of 0s
    var curr = 0;
 
    // Convert shortest subStrings
    // of 0s to 1s
    while (k > 0 && (ls.size() != 0)) {
 
      for(var i : ls)
      {
        curr = i;
        break;
      }
 
      // add according to the
      // first priority
      if (k >= curr) {
        ans += (2 * curr + 1);
        k -= curr;
      }
 
      // add according to the
      // third priority
      else {
        ans += (2 * k);
        k = 0;
      }
 
      ls.remove(curr);
    }
 
    // If more 0s can be made into 1,
    // then check for 0s at ends
    if (k > 0) {
      // Update the ans
      ans += (2 * Math.min(k, n - (ind + 1)) - 1);
      k -= Math.min(k, n - (ind + 1));
 
      if (ind > -1)
        ans += 1;
    }
 
    // If K is non-zero, then flip 0s
    // at the beginning
    if (k > 0) {
      ans += (Math.min(indf, k) * 2 - 1);
 
      if (indf > -1)
        ans += 1;
    }
 
    // Return the final weights
    return ans;
  }
 
  // Driver Code
 
  public static void main(String[] args)
  {
    // Given String str
    var s = "1110000101";
 
    var N = s.length();
 
    // Given K flips
    var K = 3;
 
    // Function Call
    System.out.println(findMax(s, N, K));
  }
}
 
// This code is contributed by phasing17


Python3




# Python 3 program of the above approach
 
# Function to find maximum sum of
# weights of binary string after
# at most K flips
def findMax( s, n, k):
 
    ans = 0;
 
    # Stores lengths of substrings
    # of the form 1..00..1s
    l = 0;
 
    # Stores the index of last 1
    # encountered in the string
    ind = -1;
 
    # Stores the index of first 1
    # encountered
    indf = -1;
 
    # Stores lengths of all substrings
    # having of 0s enclosed by 1s
    # at both ends
    ls = set([])
 
    # Traverse the string
    for i in range(n):
        # If character is 0
        if (s[i] == '0'):
            l+=1
 
        # If character is 1
        # First Priority
        elif (s[i] == '1'
                 and l > 0 and ans != 0):
            ls.add(l);
            l = 0;
 
        # Second Priority
        if (s[i] == '1') :
            ind = i;
            l = 0;
            if (indf == -1):
                indf = i;
 
            # Add according to the
            # first priority
            if (i > 0 and s[i - 1] == '1'):
                ans += 2;
            else:
                ans += 1;
 
    # Stores length of the shortest
    # substring of 0s
    curr = 0
 
    # Convert shortest substrings
    # of 0s to 1s
    while (k > 0 and len(ls)!=0):
        for i in ls:
          curr = i
          break
 
        # Add according to the
        # first priority
        if (k >= curr):
            ans += (2 * curr + 1);
            k -= curr;
 
        # Add according to the
        # third priority
        else :
            ans += (2 * k);
            k = 0;
        
        ls.remove(curr);
     
    # If more 0s can be made into 1,
    # then check for 0s at ends
    if (k > 0) :
        # Update the ans
        ans += (2 * min(k,
                        n - (ind + 1))
                - 1);
        k -= min(k, n - (ind + 1));
 
        if (ind > -1):
            ans+=1
 
    # If K is non-zero, then flip 0s
    # at the beginning
    if (k > 0):
        ans += (min(indf, k) * 2 - 1);
 
        if (indf > -1):
            ans+=1
    
    # Return the final weights
    return ans
 
# Driver Code
if __name__ == "__main__":
   
    # Given string str
    s = "1110000101";
 
    N = len(s)
 
    # Given K flips
    K = 3;
 
    # Function Call
    print(findMax(s, N, K));
 
    # This code is contributed by chitranayal


C#




// C# program of the above approach
using System;
using System.Collections.Generic;
 
class GFG
{
 
  // Function to find maximum sum of
  // weights of binary string after
  // at most K flips
  static int findMax(string s, int n, int k)
  {
    var ans = 0;
 
    // Stores lengths of substrings
    // of the form 1..00..1s
    var l = 0;
 
    // Stores the index of last 1
    // encountered in the string
    var ind = -1;
 
    // Stores the index of first 1
    // encountered
    var indf = -1;
 
    // Stores lengths of all substrings
    // having of 0s enclosed by 1s
    // at both ends
    var ls = new SortedSet<int>();
 
    // Traverse the string
    for (var i = 0; i < n; i++) {
      // If character is 0
      if (s[i] == '0')
        l += 1;
 
      // If character is 1
      // First Priority
      else if ((s[i] == '1') && (l > 0)
               && (ans != 0)) {
        ls.Add(l);
        l = 0;
      }
      // Second Priority
      if (s[i] == '1') {
        ind = i;
        l = 0;
        if (indf == -1)
          indf = i;
 
        // Add according to the
        // first priority
        if ((i > 0) && (s[i - 1] == '1'))
          ans += 2;
        else
          ans += 1;
      }
    }
 
    // Stores length of the shortest
    // substring of 0s
    var curr = 0;
 
    // Convert shortest substrings
    // of 0s to 1s
    while (k > 0 && (ls.Count != 0)) {
 
      foreach(var i in ls)
      {
        curr = i;
        break;
      }
 
      // Add according to the
      // first priority
      if (k >= curr) {
        ans += (2 * curr + 1);
        k -= curr;
      }
 
      // Add according to the
      // third priority
      else {
        ans += (2 * k);
        k = 0;
      }
 
      ls.Remove(curr);
    }
 
    // If more 0s can be made into 1,
    // then check for 0s at ends
    if (k > 0) {
      // Update the ans
      ans += (2 * Math.Min(k, n - (ind + 1)) - 1);
      k -= Math.Min(k, n - (ind + 1));
 
      if (ind > -1)
        ans += 1;
    }
 
    // If K is non-zero, then flip 0s
    // at the beginning
    if (k > 0) {
      ans += (Math.Min(indf, k) * 2 - 1);
 
      if (indf > -1)
        ans += 1;
    }
 
    // Return the final weights
    return ans;
  }
 
  // Driver Code
 
  public static void Main(string[] args)
  {
    // Given string str
    var s = "1110000101";
 
    var N = s.Length;
 
    // Given K flips
    var K = 3;
 
    // Function Call
    Console.WriteLine(findMax(s, N, K));
  }
}
 
// This code is contributed by phasing17


Javascript




// JavaScript program of the above approach
 
// Function to find maximum sum of
// weights of binary string after
// at most K flips
function findMax( s, n, k)
{
    let ans = 0;
 
    // Stores lengths of substrings
    // of the form 1..00..1s
    let l = 0;
 
    // Stores the index of last 1
    // encountered in the string
    let ind = -1;
 
    // Stores the index of first 1
    // encountered
    let indf = -1;
 
    // Stores lengths of all substrings
    // having of 0s enclosed by 1s
    // at both ends
    let ls = new Set()
 
    // Traverse the string
    for (var i = 0; i < n; i++)
    {
        // If character is 0
        if (s[i] == '0')
            l+=1
 
        // If character is 1
        // First Priority
        else if ( (s[i] == '1') && (l > 0) && (ans != 0))
        {
            ls.add(l);
            l = 0;
        }
        // Second Priority
        if (s[i] == '1')
        {
            ind = i;
            l = 0;
            if (indf == -1)
                indf = i;
 
            // Add according to the
            // first priority
            if ((i > 0) && (s[i - 1] == '1'))
                ans += 2;
            else
                ans += 1;
        }
    }
 
    // Stores length of the shortest
    // substring of 0s
    let curr = 0
 
     
     
    // Convert shortest substrings
    // of 0s to 1s
    while (k > 0 && (ls.length!=0))
    {
         
        ls1 = Array.from(ls)
        ls1.sort()
         
        for (let i of ls1)
        {
          curr = i
          break
        }
 
        // Add according to the
        // first priority
        if (k >= curr)
        {
            ans += (2 * curr + 1);
            k -= curr;
        }
 
        // Add according to the
        // third priority
        else
        {
            ans += (2 * k);
            k = 0;
        }
         
        ls.delete(curr);
    }
     
    // If more 0s can be made into 1,
    // then check for 0s at ends
    if (k > 0)
    {
        // Update the ans
        ans += (2 *  Math.min(k, n - (ind + 1))  - 1);
        k -=  Math.min(k, n - (ind + 1));
 
        if (ind > -1)
            ans+=1
    }
     
    // If K is non-zero, then flip 0s
    // at the beginning
    if (k > 0)
    {
        ans += ( Math.min(indf, k) * 2 - 1);
 
        if (indf > -1)
            ans +=1
    }
    
    // Return the final weights
    return ans
}
 
// Driver Code
 
// Given string str
let s = "1110000101";
 
let N = s.length
 
// Given K flips
let K = 3;
 
// Function Call
console.log(findMax(s, N, K));
 
 
// This code is contributed by phasing17


Output: 

14

 

Time Complexity: O(N)
Auxiliary Space: O(N)



Last Updated : 22 Dec, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads