当前位置:C++技术网 > 资讯 > 面试题:12 输出一个字符串中重复的字符并统计其个数输出

面试题:12 输出一个字符串中重复的字符并统计其个数输出

更新时间:2016-05-19 14:16:18浏览次数:1+次

在昨天的那篇文章《面试题:输入一个字符串,输出这个字符串中重复的元素及其个数》中实现出来了重复的字符及其个数,可是,我最后却说了一句重复的个数仅限于两个。这是为什么?

如上所示,一旦输入的字符串的个数多余三个,输出的结果就不满足我们的要求——只输出重复字符及其个数!可是一旦重复的字符的个数超过三个,就是出现上面的情况!在这里有一种解决方案,不过,对于一个对程序认真的程序员来说,这个解决方案不可取。那就是完整的输出字符串里的字符,然后分别对应输出字符个数,例如(假定输入的字符串是google):
g-2
o-2
o-2
g-2
这种情况也算是完成了要求,可是不严谨!这会给你一种g有四个的感觉,因此,我们需要改进算法。
先讲讲解题思路吧:我们还是利用map容器,首先统计字符的个数是否大于1,若满足则说明有重复字符,同时,我们利用string类的find()的返回值——返回要查找的元素第一次出现的位置。然后,我们定义一个vector容器来存取这个返回值。接下来,我们为其排序,使得vector里所存储的数据有序,也就是让重复的元素能够挨在一起相邻。因为接下来,我们要利用unique算法来移除相邻的重复元素,STL中的unique函数实现重复数据移除操作,并不能删除,该算法返回的是移除之后的终点,注意不能在使用原来的终点end。因此,我们需要一个iterator来接收返回值。我们将移除后的元素重新放到vector中,然后,我们在map存储的字符串中,查找我们新的vector的元素。接下来就大功告成了!(对于unique函数的操作,请看《STL中的unique函数实现重复数据移除操作》)
看看代码:
//输出字符串各个字符的个数
#include "iostream"
#include "windows.h"
#include "string"
#include "map"
#include "vector"
#include "algorithm"
#include "iterator"

using namespace std;

int main()
{

vector<int> coll,coll1;
string str;
int len;
int nn;
char word;
cin>>str;

int index;
map<char,int> counts;
len=str.length();
int i;

vector<int>::iterator pos;
for(i=0; i<len; i++)
{
word=str.at(i);
++counts[word];//将输入的字符串中的字符挨个输入到map容器
}
for(i=0; i<len; i++)
{
char cha=str.at(i);
index=str.find(cha);
map<char,int>::iterator num(counts.find(cha));//开始统计计数
if(num->second>1)
{
coll.push_back(index);
}
}
sort(coll.begin(),coll.end());
pos=unique(coll.begin(),coll.end());
//copy(coll.begin(),pos,ostream_iterator<int>(cout, " "));
copy(coll.begin(),pos,back_inserter(coll1));
//copy(coll1.begin(),coll1.end(),ostream_iterator<int>(cout," "));
for(i=0; i<coll1.size(); i++)
{
char ch=str.at(coll.at(i));
nn=str.find(ch);
map<char,int>::iterator num1(counts.find(ch));
cout<<num1->first<<" ";
cout<<num1->second<<endl;
}

cout<<endl;

system("pause");
return 0;
}
输出:

程序代码略显臃肿,或许有一些多余的操作。大家可以指出,一起优化。其实细心地读者可以发现,我们实现了第二种算法来实现"输出删除了字符串中重复的字符之后的字符串"(第一种算法《面试题:输入一个字符串,输出删除了重复的字符后的字符串》)