今天想跟大家分享 **a224. 明明愛明明** 這一題我的解題想法,有任何想討論的歡迎提出喔 ### 以下是我的程式碼 ``` #include<bits/stdc++.h> using namespace std; int main(){ string s; while(getline(cin,s)){ //change to small alpha for(int i=0;i<s.size();i++){ if(isalpha(s[i])){ s[i]=tolower(s[i]); } } sort(s.begin(),s.end()); //delete : ; , _ for(int i=0;i<s.size();i++){ if(!isalpha(s[0])){ s.erase(0,1); } } int odd=0; char nowchar=s[0]; int time=0; for(int i=0;i<s.size();i++){ if(isalpha(s[i])){ if(nowchar==s[i]){ time++; } else if(nowchar!=s[i]){ if(time%2==1) odd+=1; time=1; nowchar=s[i]; } } } if (time % 2 == 1) odd++; //output if(odd<=1) cout<<"yes !"<<endl; else cout<<"no..."<<endl; } } ``` --- ### 講解~ 1. 第一部分 ``` while(getline(cin,s)){ //change to small alpha for(int i=0;i<s.size();i++){ if(isalpha(s[i])){ s[i]=tolower(s[i]); } } ``` 這裡我用getline直接取得字串 藉著我用迴圈把字元一個一個取出來做比較 我利用了**isalpha()函式**來判斷該字元是不是字母,如果是就一律轉成小寫英文字母 再來我用了 **sort(s.begin(),s.end())的函式**把字串s排序,排完後我發現那些標點符號 : ; , _ 都被擺到了前面。 --- 2. 第二部分 基於剛剛的觀察結果,我用了**erase()函式**,我從頭開始一個一個刪除那些標點符號, ``` //delete : ; , _ for(int i=0;i<s.size();i++){ if(!isalpha(s[0])){ s.erase(0,1); } } ``` 現在可以試試看把s印出來,應該會是一個照順序排好,只有小寫英文字的字串 接著我們可以來做下一步處理了! 補充:我後來問了GPT 他給出了另一個方式 ``` // 刪除所有非字母字元 for (int i = 0; i < s.size(); ) { if (!isalpha(s[i])) { s.erase(i, 1); } else { i++; } } ``` 這裡大家就看看喜歡用哪一種方式啦,不過我的方式有可能漏掉其他不是在開頭的非字母,或者無限迴圈。 --- 3. 第三部分 ``` int odd=0; char nowchar=s[0]; int time=0; for(int i=0;i<s.size();i++){ if(isalpha(s[i])){ if(nowchar==s[i]){ time++; } else if(nowchar!=s[i]){ if(time%2==1) odd+=1; time=1; nowchar=s[i]; } } } if (time % 2 == 1) odd++; ``` 因為剛剛都把字元排好了,所以我現在的想法:我從頭開始跑,當輪到那個字元,看看跟上一個字元是不是相同的,如果相同,就把次數time加上一(代表那個字元出現的次數多一次),如果不同,那就觸發換字,開始結算目前的time,判斷該字元總共出現的次數,如果是基數,那就把odd 加上一。 至於這部分最後一行的**if (time % 2 == 1) odd++;**是因為迴圈都跑完,但是最後一部分的time還沒有結算,所以這裡要讓他直接結算 --- 4. 第四部份 ``` //output if(odd<=1) cout<<"yes !"<<endl; else cout<<"no..."<<endl; ``` 這邊說一下我對回文的理解,剛剛上一步,我們已經算出有幾個字元是出現過**基數次** 接著我們想一下: 1. 假設現在是aabbcc 沒有字元出現基數次 可以組成acbbca 2. 假設現在是aabbbcc 只有一個字元b出現基數次 可以組成acbbbca 3. 假設現在是aabbbccc 有兩個字元出現基數次 不能組成回文 所以我們依據剛剛算出的odd,如果odd<=1才是可以組成回文的 最後再把答案輸出就大功告成啦~