重复删除子字符串“10”中的字符形成的字典序最小的字符串


字典序最小的字符串是指在一组字符串中,在字典序中首先出现的字符串称为字典序最小的字符串。我们将给定一个二进制字符串(仅包含两种不同类型的字符 0 和 1),并且我们可以从给定字符串中的任何子字符串“10”中删除字符“1”,任何次数或任何时间。我们必须通过应用此方法创建字典序字符串。

示例

输入 1

字符串 str = “1101010011”

输出:000011

解释 − 因为我们只能删除字符“1”,所以我们将删除所有出现在零之前的 1。我们可以删除位于第 1、3 和 5 个索引处的“1”,并将得到字符串“1000011”。现在,我们只能删除第 0 个索引处的 1。

输入 2

字符串 str = “0011”

输出:0011

解释 − 1 的右侧没有零,这意味着我们无法更新字符串。

朴素方法

在这种方法中,我们将遍历字符串并找到“10”的组合或找到此子字符串。

我们将创建一个字符串来存储新字符串,并将新的元素添加到其中。

我们将使用 for 循环遍历上一个字符串,并将所需的字符添加到新字符串中。

我们将维护一个变量来标记我们是否正在删除任何字符,因为如果字符串正在更改,则可能再次获得新的子字符串“10”。

我们将使用 while 循环来重复检查字符串。让我们看看代码 −

示例

#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;
}

输出

The smallest string after a certain number of changes is 000011

时间和空间复杂度

上述代码的时间复杂度为 O(N*N),其中 N 是给定字符串的长度。

上述代码的空间复杂度为 O(N),因为我们将当前字符串传递给函数。

高效方法

在之前的方法中,我们每次都在更改字符串,这导致我们在每次迭代中都乘以 N。

我们可以通过一般的观察来优化结果,即如果存在一个零,它将删除其左侧的任何 1,并且在更新后,如果再次出现任何 1,它将再次删除它。

这意味着在从最后一个零出现后的字符串中,所有 1 都将消失。

我们将简单地使用 for 循环并从最后一个零开始检查,当我们从那里找到零时,我们将停止将 1 添加到答案字符串中,并且仅添加零之前的字符,在此之前我们将添加零和 1。

示例

#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;
}

输出

The smallest string after a certain number of changes is 000011

时间和空间复杂度

上述代码的时间复杂度为 O(N),因为我们只遍历字符串一次,然后反转一次。

上述代码的空间复杂度为 O(1),因为我们在这里没有使用任何额外的空间。

结论

在上面的教程中,我们学习了如何通过删除字符“1”(如果给定字符串中存在子字符串“10”)来找到给定字符串的字典序最小的字符串。我们实现了两种方法,第一种方法的时间复杂度为 O(N*N),并具有额外的线性空间。第二种方法是最佳方法,时间复杂度为 O(N),空间复杂度为常数。

更新于: 2023 年 5 月 17 日

377 次查看

开启你的 职业生涯

通过完成课程获得认证

开始学习
广告