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;
};