LeetCodeGOGOGO刷題記03——代碼優化(利用字符串流和c++11新功能來處理字符串)

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'&&paragraph[a]<='z')||(paragraph[a]>='A'&&paragraph[a]<='Z'))
                return true;
            else
                return false;
        }
    
    bool isupcha(int a, string paragraph)
        {
            if(paragraph[a]>='A'&&paragraph[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;
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章