819. Most Common Word
难度:
Medium
思路:
字符串处理问题,预先排除一部分单词,组成单词库(banned),要求找出一篇文章中出现最多的非banned单词(大小写不敏感)。
这题思路也十分清晰,首先处理文章,将其处理成一个一个单词,并全部转化为小写,然后依次插入unordered_map中,最后遍历map得到结果
其实这题的难度不大,然而常规代码并不简单,洋洋洒洒一不小心五六十行就下来了
代码:
/*
Author Owen_Q
*/
class Solution {
public:
string mostCommonWord(string paragraph, vector<string>& banned) {
re.clear();
int st = 0;
int plen = paragraph.size();
while(st<plen)
{
if(ischa(st,paragraph))
{
int pos = 0;
string words = "";
for(;st+pos<plen;pos++)
{
if(ischa(st+pos,paragraph))
{
if(isupcha(st+pos,paragraph))
paragraph[st+pos] += 'a'-'A';
words += paragraph[st+pos];
}
else
break;
}
if(find(banned.begin(),banned.end(),words)==banned.end())
{
re[words]++;
//cout << words <<endl;
}
st += pos+1;
}
else
st++;
}
string rewords;
int renum = 0;
for(auto it=re.begin();it!=re.end();it++)
{
if((*it).second>renum)
{
renum = (*it).second;
rewords = (*it).first;
}
}
return rewords;
}
private:
unordered_map<string,int> re;
bool ischa(int a, string paragraph)
{
if((paragraph[a]>='a'&¶graph[a]<='z')||(paragraph[a]>='A'&¶graph[a]<='Z'))
return true;
else
return false;
}
bool isupcha(int a, string paragraph)
{
if(paragraph[a]>='A'&¶graph[a]<='Z')
return true;
else
return false;
}
};
于是下面来研究一下代码的优化
字符串流和字符串处理函数回顾:
istringstream:
istringstream(string str)
字符串流并不是c++11的新功能,但确实是一个很容易被忽略却又十分好用的功能
该字符串流以空格作为分隔,可以将一个完整字符串分隔成多个小字符串,类似于标准输入流那样,这样就使得字符串的分隔变得十分容易,而不用再想原来那样按字符串内元素一个个手动分隔
ctype.h:
ctype.h这个库函数里确实有很多很巧的函数,虽然实现起来也不难,但充分运用这些函数可以使得代码变得十分简洁
主要有这些常用函数:
isalpha()判断字符是否为字母(大小写)
isnum()判断字符是否为数字;
ispunct()判断字符是否为特殊符号
islower()判断字符是否为小写字母
isupper()判断字符是否为大写字母
tolower()将大写字母转换为小写字母
toupper()将小写字母转换为大写字母
c++11知识回顾:
auto:
自动类型判断,其实这个功能十分简单,主要就是不用在自己定义变量类型,而是编译器可以根据传入变量的值自动判断。这个功能的好处主要就体现在长变量声明的简洁性上,比如iterator的声明,使用auto就完全可以省略冗长的iterator声明,使得代码变得十分清晰简洁
for:
for(declaration:expression)
c++11也对for循环进行了升级,除了最原始的for( ; ; )使用方式,现在也可以使用类似于python中for循环in的使用方式。这使得数组遍历变得,尤其是字符串处理变得十分方便
注意,若想改变declaration的值,记得加入引用符号
代码提升:
首先当然是字符串处理,利用for的新特性,将所有大写字母处理成小写字母,将所有非字母处理成空格用于字符串流的分隔
接着转成字符串流进行处理,对于每个单词依旧扔入unordered_map中,并在每次传入的过程中均进行一次判断,以剩下最后统一判断的代码
简单两步即可完成,整个代码变得十分清晰美观
代码:
/*
Author Owen_Q
*/
class Solution {
public:
string mostCommonWord(string paragraph, vector<string>& banned) {
for(auto &c: paragraph)
c = isalpha(c)? tolower(c): ' ';
istringstream iss(paragraph);
string words, rewords;
int renum = 0;
re.clear();
while(iss >> words)
{
if(find(banned.begin(),banned.end(),words)==banned.end())
{
re[words]++;
if(re[words]>renum)
{
renum = re[words];
rewords = words;
}
}
}
return rewords;
}
private:
unordered_map<string,int> re;
};