XX公司的笔试题:
给定一个仅包含英文字母和空格的字符串,请实现一个函数找出该字符串中出现次数最多的10个字母(不区分大小写)。
当时的解答是:
#include
#include
#include
#include
using namespace std;
bool compare_map(const pair
{
return p1.second < p2.second;
}
char* Find_top10Char(const char* str)
{
if (!str)
return NULL;
const char *pStr = str;
static char res[11] ;
memset(res, 0, sizeof(res));
map
while (*pStr != '/0')
{
char tp = *pStr;
if(*pStr == ' ')
pStr++,continue;
if (*pStr + 32 < 122) //如果是大写,转换成小写
{
tp = *pStr + 32;
}
tmp[tp]++;
pStr++;
}
map
for (int i = 0; i < 10 && !tmp.empty(); ++i)
{
iter = max_element(tmp.begin(), tmp.end(), compare_map); //效率太低
if (iter != tmp.end())
{
res[i] = iter->first;
tmp.erase(iter);
continue;
}
break;
}
return res;
}
//test
int main()
{
const char *pp = "aaajjjj jaaaaf fffjjjllllf fflllo ffoaoaaoottotrrttrwrwqwqu";
char *res = Find_top10Char(pp);
cout<
}
将源字符串中出现过的字符都记录下来,放在map容器的pair中,字符每出现多一次就将该pair的second加1。知道遍历完整个字符串。
接下来,需要对map容器根据pair的second进行排序,得到前10个元素。可是map容器本身就是已排好序的容器(根据每一个key),因此不能改变该容器的顺序,只能另谋它法了。
要想得到和map结构一样的非排序容器,可以用vector或list来完成,将pair
在此采用vector来实现:
vector
//copy(tmp.begin(), tmp.end(), back_inserter(vec));
int idx = 0; //在下面定义map迭代器处接着定义idx,老是编译错误,不知为啥
for (map
{
vec[idx] = make_pair(iter->first, iter->second);
}
partial_sort(vec.begin(), vec.begin() + 9, vec.end(), compare_map); //此时应将compare_map函数"改>"
然后再:
for (int i = 0; i < 10 && !vec.empty(); ++i)
{
pair
res[i] = pr.first;
vec.erase(vec.begin());
}
这里有几个疑问:
1.为什么改用partial_sort之后,效率就高了呢?它的原理是什么?
2.为什么要用vector而不用list呢?假如需要存放的数据很多的话,vector不是低效吗?
3.为什么构造vec对象的时候不采用vector
答:
1.partial_sort是通过堆排序实现的,具体看“从partial_sort挖掘堆排序”这篇。
2.正是考虑到vector是顺序存储元素的,所以预先分配了足够的空间,然后通过下标即可对其每个元素赋值。
3.这样的用法本身有问题,在模板类vector中的iterator只是一个unsigned int类型,而map或list等模板类中的iterator却是class,当然不能通过编译,起码VC6不行。