Day11 2023/01/18
难度:简单
题目
将一个英文语句以单词为单位逆序排放,例如“I am a boy”,逆序排放后为“boy a am I”,所有单词之间用一个空格隔开,语句中除了英文字母外,不再包含其他字符,数据范围:输入的字符串长度满足:1 ≤n ≤ 1000
输入描述:
输入一个英文语句,每个单词用空格隔开。保证输入只包含空格和字母。
输出描述:
得到逆序的句子
示例
输入:I am a boy
输出:boy a am I
思路一
首先将字符串整体反转,然后以空格为界,再反转各个单词。
原字符串:i am a boy
第一次反转:yob a ma i
第二次反转:boy a am i
思路二
利用cin流遇空格就结束,因此输入的时候单词和单词之间就形成自然分割了,然后反向拼接字符串,然后输出即可。
思路三
利用栈的先进后出,同方法一一样的方式分割字符串并进栈,然后再出栈即可,如图所示:
关键点
- 理解思路一中,是如何分割字符串的,利用的是我们熟悉的双指针的方式。
算法实现
c++代码实现1-两次反转
#include<iostream>
#include<string>
#include<algorithm>
#include <stack>
using namespace std;
//方法一:两次反转
int main () {
cout << "请输入字符串:";
string str;
getline(cin, str); //获取字符串
int len = str.length(); //字符串长度
reverse(str.begin(), str.end()); //先整体反转第一遍
for (int i = 0; i < len; i++) {
int j = i; //对每个单词循环前都让i和j指向同一个位置
while (j < len && str[j] != ' ') j++; //以空格确定每个单词
reverse(str.begin() + i, str.begin() + j);
i = j; //指向下一个单词的前一个位置
}
cout << "逆序之后:" << str << endl;
}
- 时间复杂度 --- 遍历整个字符串, n为字符串长度
- 空间复杂度 --- 字符串为必要空间,无额外空间
c++代码实现2-输入时反向拼接
#include<iostream>
#include<string>
#include<algorithm>
#include <stack>
using namespace std;
//方法二:输入时反向拼接
int main(){
string s, temp;
while(cin >> temp){ //输入字符串
temp += " " + s; //每个单词加在字符串前面
s = temp;
if(cin.get() == '\n') break;
}
cout << s << endl;
return 0;
}
- 时间复杂度 --- 遍历整个字符串, n为字符串长度
- 空间复杂度 --- 字符串为必要空间,无额外空间
c++代码实现3-分割字符串+栈
#include<iostream>
#include<string>
#include<algorithm>
#include <stack>
using namespace std;
//方法三:栈
int main(){
cout << "请输入字符串:";
string s;
getline(cin, s); //获取字符串
int n = s.length();
stack<string> st;
for(int i = 0; i < n; i++){ //遍历字符串,找到单词并入栈
int j = i;
while(j < n && s[j] != ' ') //以空格为界,分割单词
j++;
st.push(s.substr(i, j - i)); //单词进栈
i = j;
}
cout << "逆序之后:";
while(!st.empty()){ //栈遵循先进后处,单词顺序是反的
cout << st.top() << " ";
st.pop();
}
return 0;
}
- 时间复杂度 --- 遍历整个字符串, n为字符串长度
- 空间复杂度 --- 栈空最坏情况下长度为n
总结
-
有时可以利用常用数据结构的特点去解题。
-
可以利用方法二中分割字符串的方式和方法三中输出的方式,两者结合代码可以更加简洁。