题目描述
实现删除字符串中出现次数最少的字符,若多个字符出现次数一样,则都删除。输出删除这些单词后的字符串,字符串中其它字符保持原来的顺序。
输入描述:
字符串只包含小写英文字母, 不考虑非法输入,输入的字符串长度小于等于20个字节。
输出描述:
删除字符串中出现次数最少的字符后的字符串。
示例1
输入
abcdd
输出
dd
一,第一版代码
如下所示:
typedef struct
{
int word;
int num;
}stu;
stu stu_count[27];
for(int i=0;i<27;i++)
{
stu_count[i].word='a'+i;
stu_count[i].num=0;
}
这个时候自己单纯地以为这样处理很方便但是我没有想到隐藏的问题所在,继续往下,我目的是想要将出现的字母的次数都记录在stu[i].num中,但是却没有实现应有的功能,原因是我没有将字母跟下标的关系理解清楚,导致出现了错误,这时是不可行的,错误代码为:
for(int j=0;j<27;++j)
{
for(unsigned int i=0;i<str.length();++i)
{
if(str[i]==stu_count[j].word)
stu_count[j].num++;
//cout<< stu_count[j].num<<endl;
}
}
假如这一步处理成功,那么下一步是不是应该求出出现的最小次数了,我天真地写出代码:
int min = stu_count[0].num;
cout<<min<<endl;
for(int i=1;i<27;++i)
{
if(stu_count[i].num<min)
min=stu_count[i].num;
}
写到这个的时候我还没有发现问题所在,于是我将输出写完,代码如下:
for(unsigned int i=0;i<str.length();++i)
{
for(int j=0;j<27;++j)
{
if(stu_count[j].num>min)
cout<<str[i];
}
}
到这个时候运行后我才发现,我没有将下标跟字母联系在一起,这是所有问题所在,肯定不会得出正确的输出。
二,于是改正代码如下:
仔细想想怎样才可以将字母跟下标联系在一起,那就是将字母转换为数字,这个时候就出现了字符间的相减,如下所示
for(int i=0;i<26;i++)
a[i]=0;
for(unsigned int i=0;i<str.length();++i)
a[str[i]-'a']++;
是不是很巧妙地实现了要求,这个时候a[]数组中存放的就是对应字母的个数,接下来同样是进行最小值求解,直接在循环中使用If语句进行判断,如下所示:
min=a[str[0]-'a'];
for(unsigned int i=0;i<str.length();++i)
{
if(a[str[i]-'a']<=min)
min=a[str[i]-'a'];
}
上面提取出了最小的出现的次数,下面输出的时候就可以根据这个最小值进行判断,然后输出正确的结果,如下
for(unsigned int i=0;i<str.length();++i)
{
if(a[str[i]-'a']>min)
cout<<str[i];
}
cout<<endl;
这里一定要注意加上cout<<endl;不加上结果输出不正确,这是一个要注意的点,
三,最后的完整代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
int min;
int a[26];
while(cin>>str)
{
for(int i=0;i<26;i++)
a[i]=0;
for(unsigned int i=0;i<str.length();++i)
a[str[i]-'a']++;
min=a[str[0]-'a'];
for(unsigned int i=0;i<str.length();++i)
{
if(a[str[i]-'a']<=min)
min=a[str[i]-'a'];
}
for(unsigned int i=0;i<str.length();++i)
{
if(a[str[i]-'a']>min)
cout<<str[i];
}
cout<<endl;
}
return 0;
}