文章目錄
- 💯前言
- 💯題目描述
- 輸入格式
- 輸出格式
- 樣例 #1
- 樣例輸入 #1
- 樣例輸出 #1
- 💯一、我的做法
- 代碼實現:
- 代碼解析
- 思路分析
- 💯二、老師的第一種做法
- 代碼實現:
- 代碼解析
- 思路分析
- 💯三、C++ `reverse` 函數介紹
- `reverse` 函數原型:
- 示例:
- 優點
- 💯四、老師的第二種做法:使用 `reverse` 函數
- 代碼實現:
- 代碼解析
- 思路分析
- 💯五、對比分析
- 💯六、拓展
- 💯小結
- 最開始的解法不通過
- 老師優化后通過
💯前言
- 在計算機科學中,字符串處理是一個非常基礎且常見的任務。本題主要圍繞如何將一個句子中的每個單詞反轉來進行練習。這個問題不僅考察了對字符串操作的理解,還涉及了不同的解決方法。在本篇文章中,我們將詳細探討我自己的做法、老師提出的兩種做法,并深入講解C++中
reverse
函數的使用,最后通過對比和拓展分析這些方法的優缺點。
C++ 參考手冊
💯題目描述
B2122 單詞翻轉
小明同學寫單詞的時候喜歡反著寫,比如 hello
他會寫成 olleh
。給出小明同學寫的一個句子,請你將所有的單詞復原。
輸入格式
共一行,一個字符串表示句子,單詞之間以空格分隔。
輸出格式
每個單詞一行。
樣例 #1
樣例輸入 #1
olleh dlrow
樣例輸出 #1
hello
world
💯一、我的做法
代碼實現:
#include <iostream>
#include <string>
using namespace std;int main()
{string s;while(cin >> s){for(int i = s.size() - 1; i >= 0; i--){cout << s[i];}cout << endl;}return 0;
}
代碼解析
在這個實現中,我選擇了通過手動反轉每個單詞的字符來恢復正確的單詞順序。
-
變量聲明:
string s;
:聲明一個字符串變量s
用于存儲從輸入中讀取的每個單詞。
-
讀取輸入:
while(cin >> s)
:使用cin >> s
讀取一個單詞,直到沒有更多輸入。
-
反轉每個單詞:
for(int i = s.size() - 1; i >= 0; i--)
:我們使用一個從單詞末尾到開頭的for
循環,通過訪問每個字符并逆序輸出,來實現反轉操作。
-
輸出每個單詞:
cout << s[i];
:逐個輸出反轉后的字符。
-
換行:
- 每個單詞輸出后,使用
cout << endl;
換行,確保每個單詞占一行。
- 每個單詞輸出后,使用
思路分析
這段代碼通過遍歷每個字符并從末尾到開頭進行輸出來實現反轉。通過這種手動操作字符的方式,能夠準確地完成任務。它的優點是直接且易于理解,但缺點是代碼稍顯冗長,且沒有利用C++標準庫提供的便捷工具。
💯二、老師的第一種做法
老師給出的第一種做法是通過手動交換字符串中的字符來反轉單詞。下面是老師的代碼實現:
代碼實現:
#include <iostream>
#include <cstring>
using namespace std;int main()
{string str;while(cin >> str){int left = 0;int right = str.size() - 1;while(left < right){char tmp = str[left];str[left] = str[right];str[right] = tmp;left++;right--;}cout << str << endl;}return 0;
}
代碼解析
老師的做法同樣采用了字符交換的方式來反轉每個單詞。其關鍵點在于通過兩個指針從字符串的兩端向中間移動,交換字符,直到完成反轉。
-
初始化兩個指針:
int left = 0; int right = str.size() - 1;
:left
和right
分別是指向字符串開始和結束的兩個指針。
-
交換字符:
char tmp = str[left]; str[left] = str[right]; str[right] = tmp;
:通過一個臨時變量tmp
來交換str[left]
和str[right]
。
-
逐步移動指針:
left++
和right--
:交換后,left
指針向右移動,right
指針向左移動,逐步將字符串反轉。
-
輸出反轉后的字符串:
cout << str << endl;
:輸出反轉后的單詞。
思路分析
老師的做法通過交換字符來反轉字符串,使用了雙指針的技巧,這種方法比我的做法更具效率,因為它只需要一次遍歷,每次只交換兩個字符。相比手動逐個輸出字符,這種方法更符合常見的反轉思路,代碼更簡潔。
💯三、C++ reverse
函數介紹
在C++標準庫中,提供了一個名為 reverse
的函數,它可以輕松地反轉一個容器(例如字符串、數組等)的元素順序。該函數位于 <algorithm>
頭文件中,使用時非常方便。
reverse
函數原型:
void reverse(BidirectionalIterator first, BidirectionalIterator last);
- first:指向待反轉區間的起始元素的迭代器。
- last:指向待反轉區間的結束元素的迭代器。
該函數會反轉區間 [first, last)
中的元素。
示例:
string s = "abcd";
reverse(s.begin(), s.end());
cout << s << endl; // 輸出 "dcba"
優點
- 簡潔:C++
reverse
函數將反轉操作封裝得非常簡潔。只需調用一次reverse
,就能完成字符串或數組的反轉,代碼更加清晰易懂。 - 高效:
reverse
內部實現通常采用類似于雙指針交換的方式,性能非常高。
💯四、老師的第二種做法:使用 reverse
函數
老師的第二種做法直接利用了 C++ STL 中的 reverse
函數,這使得反轉操作變得更加簡便。
代碼實現:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;int main()
{string str;while (cin >> str){reverse(str.begin(), str.end());cout << str << endl;}return 0;
}
代碼解析
這段代碼通過 reverse
函數反轉字符串:
-
使用
reverse
函數:reverse(str.begin(), str.end());
:直接使用reverse
函數來反轉字符串str
。
-
輸出反轉后的字符串:
cout << str << endl;
:輸出每個反轉后的單詞,并換行。
思路分析
這種做法通過使用 C++ STL 中的現成函數來簡化代碼。reverse
函數提供了高效且簡潔的反轉操作,比手動交換字符或逐個輸出字符的方法要簡單得多。
💯五、對比分析
-
我的做法:
- 優點:代碼簡單,容易理解,適用于初學者。
- 缺點:冗長,效率較低,特別是手動反轉每個字符時,不夠高效。
-
老師的第一種做法:
- 優點:通過雙指針交換字符,比手動輸出字符更高效。
- 缺點:代碼較為復雜,理解起來可能稍微困難。
-
老師的第二種做法:
- 優點:使用
reverse
函數,代碼最簡潔,符合C++的標準庫優勢,效率高。 - 缺點:可能需要對
reverse
函數有一定的了解。
- 優點:使用
💯六、拓展
除了 reverse
函數外,我們還可以用其他方式來處理字符串或數組的反轉操作:
- 利用棧:將字符壓入棧中,然后從棧中彈出字符來實現反轉。
- 遞歸:通過遞歸函數逐步將字符串或數組的字符進行反轉。
💯小結
通過對比不同的做法,我們可以看到,C++提供了多種有效的反轉策略。通過手動字符交換、使用 reverse
函數,甚至使用 STL 容器的其他方法,我們可以靈活地選擇最適合問題需求的解決方案。在實際開發中,選擇合適的工具和方法,不僅能提高代碼的可讀性,還能提高程序的效率。
最開始的解法不通過
#include <iostream>
#include <string>
using namespace std;int main()
{string s;getline(cin, s);int i = 0;int index = 0;for(i = 0; i < s.size(); i++){if(s[i] == ' '){for(int j = i - 1; j >= index; j--)cout << s[j];cout << endl;index = i + 1; }else if(i == s.size() - 1){for(int j = i; j >= index; j--)cout << s[j];cout << endl;} } return 0;
}
老師優化后通過
#include <iostream>
#include <string>
using namespace std;int main()
{string s;getline(cin, s);int i = 0;int index = 0;for (i = 0; i < s.size() - 1; i++){if (s[i] == ' '){for (int j = i - 1; j >= index; j--){cout << s[j];}cout << endl;index = i + 1;}else if (i == s.size() - 2){for (int j = i; j >= index; j--){cout << s[j];}cout << endl;}}return 0;
}