题目描述
给一个全是小写字母的字符串str,删除多余字符,使得每种字符只保留一个,并且让最终结果字符串字典序最小。
输入描述:
输入包含一行字符串,代表str(1 \leq length_{str} \leq 10^5 )(1≤length
str
≤10
5
)。
输出描述:
输出一行,代表删除后的字符串。
示例1
输入
复制
acbc
输出
复制
abc
示例2
输入
复制
dbcacbca
输出
复制
dabc
备注:
时间复杂度O(n)O(n),额外空间复杂度O(1)O(1)。
#include<iostream>
#include<string>
using namespace std;
char res[30];//最多只有26个字母
int map[30]; //统计每个字母出现的次数
int main()
{
string s;
cin>>s;
for(int i=0;i<s.length();i++)
map[ s[i]-'a' ]++;
int index=0,l=0,r=0;
while(r< s.length())
{
if( map[ s[r]-'a' ]==-1 || --map[ s[r]-'a' ]>0 ) // 当前字符已经选择过了,不再考虑 || 当前字符-1后面还可以再选,不再考虑
r++;
else //当前字符需要考虑并且之后不会再出现 ,在L...R中找到asicc最小的字符位置
{
int pick=-1;
for( int i=l;i<=r;i++) //选取最小的未被选取过的asicc码最小的字符位置
{
if( map[ s[i]-'a' ] !=-1 && ( pick==-1 || s[i]<s[pick] ) )
{
pick=i;
}
}
res[index++]=s[pick];//放入res中
//因为下一次遍历从 pick+1开始,上一次多减去的部分加上
for(int i=pick+1;i<=r;i++)
{
if( map[ s[i]-'a' ]!=-1 )
map[ s[i]-'a' ]++;
}
map[s[pick]-'a']=-1;
l=pick+1;
r=l;
}
}
printf("%s",res);
return 0;
}