Make Palindrome binary string with exactly β€˜a’ 0s and β€˜b’ 1s by replacing wild card '?'


When dealing with string manipulation problems, it's common to encounter scenarios where we need to transform a given string into a specific pattern or format. One such problem is making a palindrome binary string with a certain number of '0's and '1's while replacing wildcard characters represented by '?'.

In this article, we will explore an efficient algorithmic approach to solve this problem using C++. We'll discuss the problem statement, and its approach, and analyze the time and space complexity of the algorithm.

Problem Statement

Given a string consisting of '0's, '1's, and wildcard characters '?', we need to convert it into a palindromic binary string by replacing the '?' characters. The final palindrome string should contain exactly the 'a' number of '0's and 'b' number of '1's, where 'a' and 'b' are given integers. If it is not possible to form such a palindrome, we should return -1.

Approach

  • Initialize two pointers, 'left' and 'right,' pointing to the start and end of the string, respectively.

  • Use a for loop to count the occurrences of '0's and '1's. This step helps us determine how many '0's and '1's are already present in the string. Then, decrement the values of 'a' and 'b' accordingly.

  • Iterate over the string while 'left' is less than 'right':

    • If both 'S[left]' and 'S[right]' are '?' characters:

      • set 'S[left]' and 'S[right]' to '0' and decrement 'a' by 2, if the count of '0's (denoted by 'a') is greater than the count of '1's (denoted by 'b'),

      • otherwise, set 'S[left]' and 'S[right]' to '1' and decrement 'b' by 2.

    • If 'S[left]' is '?' and 'S[right]' is not '?':

      • set 'S[left]' to '0' and decrement 'a' by 1, if S[right] equals to '0'.

      • otherwise, set 'S[left]' to '1' and decrement 'b' by 1.

    • If 'S[right]' is '?' and 'S[left]' is not '?':

      • set 'S[right]' to '1' and decrement 'b' by 1, if S[left] equals to '1'.

      • otherwise, set 'S[right]' to '0' and decrement 'a' by 1.

    • If 'S[left]' is not '?' and 'S[right]' is not '?' but they are not equal, it is impossible to form a palindrome, so return βˆ’1.

    • Move the 'left' pointer to the right of the string and the 'right' pointer to the left.

  • For the strings of odd length and the middle element as'?':

    • If the count of '0's ('a') is greater than the count of '1's ('b'), set the middle element to '0' and decrement 'a' by 1.

    • Otherwise, set the middle character to '1' and decrement 'b' by 1.

  • Check if 'a' and 'b' are both zero. If they are, return the final palindromic binary string. Otherwise, return βˆ’1.

Example

Now, let us implement the above approach in different programming languages: C, C++, Java, and Python βˆ’

#include <stdio.h>
#include <string.h>

// Function to convert the string
// to a binary palindromic string with 'a' 0's and 'b' 1's
char* palindromicString(char S[], int a, int b){
   int left = 0;
   int right = strlen(S) - 1;

   // count '0's and '1's in S
   for (int i = 0; i < strlen(S); i++) {
      if (S[i] == '0') {
         a--;
      } else if (S[i] == '1') {
         b--;
      }
   }

   // Replace '?' characters based on conditions
   while (left < right) {
      if (S[left] == '?' && S[right] == '?') {
         if (a > b) {
            S[left] = S[right] = '0';
            a -= 2;
         } else {
            S[left] = S[right] = '1';
            b -= 2;
         }
      } else if (S[left] == '?' && S[right] != '?') {
         if (S[right] == '0') {
            S[left] = S[right];
            a--;
         } else {
            S[left] = S[right];
            b--;
         }
      } else if (S[right] == '?' && S[left] != '?') {
         if (S[left] == '0') {
            S[right] = S[left];
            a--;
         } else {
            S[right] = S[left];
            b--;
         }
      } else if (S[left] != S[right]) {
         return "-1";
      }

      left++;
      right--;
   }
   // If the string length is odd, handle the case of the middle character.
   if (strlen(S) % 2 != 0 && S[strlen(S) / 2] == '?') {
      if (a > b) {
         S[strlen(S) / 2] = '0';
         a--;
      } else {
         S[strlen(S) / 2] = '1';
         b--;
      }
   }

   // Return the palindromic binary string if 'a' and 'b' are both zero, else return -1.
   if (a == 0 && b == 0) {
      return S;
   } else {
      return "-1";
   }
}
int main(){
   char str[] = "01?1???";
   int a = 4, b = 3;

   printf("%s\n", palindromicString(str, a, b));
   return 0;
}

Output

0101010
#include<iostream>
#include<string>
using namespace std;

// Function to convert the string
// to a binary palindromic string with 'a' 0's and 'b' 1's
string palindromicString(string S, int a, int b) {
   int left = 0;
   int right = S.size() - 1;

   // count '0's and '1's in S
   for(auto s: S){
      if(s=='0'){
         a--;
      } else if(s=='1'){
         b--;
      }
   }
   
   // Replace '?' characters based on conditions
   while (left < right) {
      
      if (S[left] == '?' && S[right] == '?') {
         if (a > b) {
            S[left] = S[right] = '0';
            a -= 2;
         } else{
            S[left] = S[right] = '1';
            b -= 2;
         } 
      } else if (S[left] == '?' && S[right] != '?') {
         if(S[right]=='0'){
            S[left]=S[right];
            a--;
         } else{
            S[left]=S[right];
            b--;
         }
      } else if (S[right] == '?' && S[left] != '?') {
         if(S[left]=='0'){
            S[right]=S[left];
            a--;
         } else{
            S[right]=S[left];
            b--;
         }
      } else if (S[left] != S[right]) {
         return "-1";
      }

      left++;
      right--;
   }

   // If the string length is odd, handle the case of the middle character.
   if (S.size() % 2 != 0 && S[S.size() / 2] == '?') {
      if (a > b) {
         S[S.size() / 2] = '0';
         a--;
      } else {
         S[S.size() / 2] = '1';
         b--;
      }
   }

   // Return the palindromic binary string if 'a' and 'b' are both zero, else return -1.
   if (a == 0 && b == 0) {
      return S;
   } else {
      return "-1";
   }
} 
int main() {
   string str = "01?1???";
   int a = 4, b = 3;
   cout << palindromicString(str, a, b) << endl;
   return 0;
}	  

Output

0101010
public class PalindromicString {
   static String palindromicString(String str, int a, int b) {
      char[] S = str.toCharArray();
      int left = 0;
      int right = S.length - 1;

      // count '0's and '1's in S
      for (char s : S) {
         if (s == '0') {
            a--;
         } else if (s == '1') {
            b--;
         }
      }
      // Replace '?' characters based on conditions
      while (left < right) {
         if (S[left] == '?' && S[right] == '?') {
            if (a > b) {
               S[left] = S[right] = '0';
               a -= 2;
            } else {
               S[left] = S[right] = '1';
               b -= 2;
            }
         } else if (S[left] == '?' && S[right] != '?') {
            if (S[right] == '0') {
               S[left] = S[right];
               a--;
            } else {
               S[left] = S[right];
               b--;
            }
         } else if (S[right] == '?' && S[left] != '?') {
            if (S[left] == '0') {
               S[right] = S[left];
               a--;
            } else {
               S[right] = S[left];
               b--;
            }
         } else if (S[left] != S[right]) {
            return "-1";
         }

         left++;
         right--;
      }
      // If the string length is odd, handle the case of the middle character.
      if (S.length % 2 != 0 && S[S.length / 2] == '?') {
         if (a > b) {
            S[S.length / 2] = '0';
            a--;
         } else {
            S[S.length / 2] = '1';
            b--;
         }
      }

      // Return the palindromic binary string if 'a' and 'b' are both zero, else return -1.
      if (a == 0 && b == 0) {
         return new String(S);
      } else {
         return "-1";
      }
   }
   public static void main(String[] args) {
      String str = "01?1???";
      int a = 4, b = 3;

      System.out.println(palindromicString(str, a, b));
   }
}

Output

0101010
def palindromic_string(s, a, b):
   S = list(s)
   left = 0
   right = len(S) - 1

   # count '0's and '1's in S
   for char in S:
      if char == '0':
         a -= 1
      elif char == '1':
         b -= 1

   # Replace '?' characters based on conditions
   while left < right:

      if S[left] == '?' and S[right] == '?':
         if a > b:
            S[left] = S[right] = '0'
            a -= 2
         else:
            S[left] = S[right] = '1'
            b -= 2
      elif S[left] == '?' and S[right] != '?':
         if S[right] == '0':
            S[left] = S[right]
            a -= 1
         else:
            S[left] = S[right]
            b -= 1
      elif S[right] == '?' and S[left] != '?':
         if S[left] == '0':
            S[right] = S[left]
            a -= 1
         else:
            S[right] = S[left]
            b -= 1
      elif S[left] != S[right]:
         return "-1"

      left += 1
      right -= 1

   # If the string length is odd, handle the case of the middle character.
   if len(S) % 2 != 0 and S[len(S) // 2] == '?':
      if a > b:
         S[len(S) // 2] = '0'
         a -= 1
      else:
         S[len(S) // 2] = '1'
         b -= 1

   # Return the palindromic binary string if 'a' and 'b' are both zero, else return -1.
   if a == 0 and b == 0:
      return ''.join(S)
   else:
      return "-1"


if __name__ == "__main__":
   s = "01?1???"
   a, b = 4, 3

   print(palindromic_string(s, a, b))

Output

0101010

Complexity Analysis

Time Complexity βˆ’ The algorithm performs a forward pass over the string to count the occurrences of '0's and '1's, which takes O(N) time, where N is the length of the string. Then, it iterates over the string from both ends, which takes O(N/2). Overall, the time complexity of the solution is O(N).

Space Complexity βˆ’ Due to the necessity to store the input string and a few other variables that require constant space, the solution has an O(N) space complexity.

Test Case

Test case → "01?1???", a=4, b=3
  • The input string S is set as "01?1???" and a is set to 4, and b is set to 3.

  • The palindromicString function is called with the given parameters.

  • The function starts by initializing the left and right pointers to the beginning and end of the string S, respectively.

  • Iterating through each character in S to count the occurrences of '0' and '1' and decrement a and b accordingly, results into a=3 and b=1, since there is already one '0' and two '1's in the string.

  • The function enters a while loop that continues until the left pointer crosses the right pointer.

  • Inside the while loop, the function checks various conditions to replace '?' characters based on the counts of '0' and '1'.

    • In the first iteration, S[left] is '0' and S[right] is '?'. Since S[left] is '0', it replaces S[right] with '0' and decrements a by 1, so, now a=2.

    • The updated string becomes "01?1??0".

    • The left pointer is incremented, and the right pointer is decremented.

    • In the second iteration, S[left] is '1' and S[right] is '?'. Since S[left] is '1', it replaces S[right] with '1' and decrements b by 1, so, now b=1.

    • The updated string becomes "01?1?10".

    • The pointers are updated.

    • In the third iteration, S[left] is '?' and S[right] is '?'. Since a is greater than b, both '?' characters are replaced with '0', and a is decremented by 2, so now a=0.

    • The pointers are updated and overlap this time. So, the while loop discontinues and the string becomes "0101010".

  • The function checks the case of the middle character. Since the length is odd but the middle character is '1', it doesn't check the middle element condition.

  • Finally, the function checks if both a and b are zero. Since a is 0 and b is 0, the modified string "0101010" is returned.

  • The result is printed to the console, which is "0101010".

Conclusion

In this article, we examined an effective algorithm for reusing the wildcard character '?' to transform a given string into a palindrome. We can make sure the final string contains precisely the 'a' number of '0's and 'b' number of '1's by carefully changing the '?' characters based on particular conditions. We went over the stepβˆ’byβˆ’step algorithm, offered a C++, C, Java, and Python implementation, and examined the solution's time and space complexity.

Updated on: 23-Jan-2024

68 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements