Lexicographically smallest string formed repeatedly deleting a character from substring ‘10’


Lexicographically smallest string means among the set of strings is the string which appears first in the dictionary order is known as a lexicographically smallest string. We will be given a binary string (that contains only two different types of characters 0 and 1) and we can delete character ‘1’ from any substring ‘10’ from the given string at any number or time. We have to create the lexicographic string by applying this method.

Sample Examples

Input 1

string str = “1101010011”

Output: 000011

Explanation − As we can only remove the character ‘1’ so will remove all the ones that are present before the zeroes. We can remove ‘1’ present at the 1st, 3rd, and 5th index and will get the string ‘1000011’. Now, we can only remove one present at the 0th index.

Input 2

string str = “0011”

Output: 0011

Explanation − There is no zero present on the right side of the one which means we cannot update the string.

Naive Approach

In this approach, we will traverse over the string and will find the combination of the ‘10’ or find this substring.

We will create a string to store the new string and will add the new elements in them.

We will traverse over the previous string using the for loop and will add the required character to the new string.

We will maintain a variable to mark if we are removing any character because if the string is changing then there may be any possibility of again getting a new substring ‘10’.

We will use the while loop to do repetitive checking of the string. Let us see the code −

Example

#include <bits/stdc++.h>
using namespace std;
// function to get the lexicographically smallest string 
string lexSmall(string str){
   string ans = ""; // string to store the answer 
   bool flag = true; // variable to mark the changes done     
   while(flag){
      flag = false;
      int len = str.length(); // getting size of the string         
      for(int i=0; i<len; i++){
         if(str[i] == '0'){
            ans += str[i];
         }
         else if(i != len-1 && str[i+1] == '0'){
            // current index is 1 and next is 0
            // so skip this and mark the flat true 
            // indicating the change in the string 
            flag = true;
            continue;
         }
         else{
            ans += str[i];
         }
      }
      if(flag){
         str = ans;
         ans = "";
      }
   }
   return ans;
}
int main(){
   string str = "1101010011"; // given string     
   // calling the function to get the required string 
   cout<<"The smallest string after a certain number of changes is "<<lexSmall(str)<<endl;
   return 0;
}

Output

The smallest string after a certain number of changes is 000011

Time and Space Complexity

The time complexity of the above code O(N*N) where N is the length of the given string.

The space complexity of the above code is O(N) as we are passing our current string to the function.

Efficient Approach

In the previous approach we are changing the string every time which cost us a multiplication of N in every iteration.

We can optimize the result by the general observation that if there is a zero present it will remove anyone present just left to it and after the updation, if anyone again occurs then it will again remove it.

This means in the string after the occurrence of the first zero from the last all the ones will disappear.

We will simply use the for loop and check from the last for the zero, when we hit the zero from there, we will stop adding ones to the answer string and only add the character zero before that we will add the both zero and one.

Example

#include <bits/stdc++.h>
using namespace std;
// function to get the lexicographically smallest string 
string lexSmall(string& str){
   string ans = ""; // string to store the answer 
   bool flag = false; // variable to mark the zero
   int len = str.length(); // getting length of the string     
   for(int i=len-1 ; i >= 0; i--){
      if(str[i] == '0'){
         ans += str[i];
         flag = true;
      }
      else if(flag){
         // flag is true means earlier there is a zero present 
         // so, no need to add this current character 
         continue;
      }
      else{
         ans += str[i];
      }
   }
   // reversing the current string 
   reverse(ans.begin(), ans.end());    
   return ans;
}
int main(){
   string str = "1101010011"; // given string     
   // calling the function to get the required string 
   cout<<"The smallest string after a certain number of changes is "<<lexSmall(str)<<endl;
   return 0;
}

Output

The smallest string after a certain number of changes is 000011

Time and Space Complexity

The time complexity of the above code is O(N), as we are just moving over the string only once and once reversing it.

The space complexity of the above code is O(1), as we are not using any extra space here.

Conclusion

In the above tutorial, we have learned how to find the lexicographically smallest string from the given string by removing the character ‘1’ if any occurrence of sub-string ‘10’ is present in the given string. We have implemented two approaches first, with the time complexity of O(N*N) and with extra linear space. Second, the approach is optimal with the O(N) time complexity and constant space.

Updated on: 17-May-2023

226 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements