A.单词反转

单词反转算法
本文介绍了一个简单的单词反转算法,该算法通过使用栈来实现对输入英文句子中每个单词的反转,并提供了一个C++实现示例。

A.单词反转

Time Limit: 1000 MSMemory Limit: 65536 KB
Total Submissions: 669Accepted: 326

Description


给你一些英文句子,请将这些句子中的每个英语单词反转,然后再将其输出。这里所说的英语单词仅由大、小写英文字母组成。




Input


多个英文句子,每句占一行,且每句不超过80个字符。



Output


按题目要求输出。



Sample Input


Hello world!
Happy programming, happy life!

Sample Output


olleH dlrow!
yppaH gnimmargorp, yppah efil!
解题思路:利用栈简单模拟 即可

Source



2013 Anhui College Student Programming Contest--ahfywff
#include<iostream>
#include<string>
#include<stack>
#include<cstring>
using namespace std;
string str;
int main() {
	while(getline(cin,str)) {
		int len=str.length();
		stack<char> s;
		for(int i=0; i< len ; i++) {
			if(isalpha(str[i])) {
				s.push(str[i]);
			} else {
				while(!s.empty()) {
					cout<<s.top();
					s.pop();
				}
				cout<<str[i];
			}
		}
		cout<<endl;
	}
	return 0;
}


<think>我们正在解决的问题是:不使用atoi实现单词顺序反转的方法。注意,用户要求的是“单词顺序反转”,而不是字符串转整数。参考引用[1]和[3]中,都是关于反转字符串中的单词顺序(整个句子中单词的顺序反转,而不是每个单词的字母反转)或反转每个单词的字母(但单词顺序不变)。根据引用[1]和[3]的示例,我们可以明确: - 引用[1]:反转字符串中的单词(整个句子的单词顺序反转)。例如:"the sky is blue" -> "blue is sky the" - 引用[3]:反转每个单词的字母(单词顺序不变)。例如:"Let's take LeetCode contest" -> "s'teL ekat edoCteeL tsetnoc" 用户要求的是“单词顺序反转”,即整个句子中单词的顺序反转,而不是每个单词内的字母反转。因此,我们应该按照引用[1]的方法。 但是,用户提到“不使用atoi”,而atoi是字符串转整数的函数,与反转单词顺序无关。由于用户之前的问题是关于字符串转整数(不使用atoi),而当前问题突然转向反转单词顺序,可能用户是想解决另一个问题?或者是对之前问题的扩展? 从用户的问题描述:“我想在不使用atoi的情况下实现单词顺序反转的方法”,这里可能有两个独立的问题: 1. 之前的问题:实现字符串转整数(不用atoi)——已经解决。 2. 当前问题:实现单词顺序反转(并且要求不使用atoi)——但反转单词顺序并不需要用到atoi,所以这个要求有点奇怪。 我们只需关注单词顺序反转。因此,忽略atoi(因为反转单词顺序根本不会用到atoi),我们直接实现反转字符串中的单词顺序。 实现思路(参考引用[1]): 1. 去除字符串的前后空格。 2. 将字符串按空格分割成单词数组(注意可能有多个连续空格,引用[1]中使用split("\\s+")处理)。 3. 反转整个单词数组(即第一个单词和最后一个单词交换,第二个和倒数第二个交换,以此类推)。 4.反转后的单词数组用单个空格连接起来,并返回。 注意:引用[1]的Java代码中,先分割,然后反转整个数组,再拼接。我们也可以用类似方法。 但是,用户可能希望用C++实现?因为之前的字符串转整数是用C++写的。不过用户没有明确语言,我们这里用C++实现。 C++实现步骤: 1. 使用双指针去除前后空格(或者使用标准库函数)。 2. 从字符串中提取单词(跳过连续空格)。 3.单词存入一个容器(如vector<string>)。 4. 反转容器中的单词顺序。 5. 将容器中的单词用空格连接起来。 代码示例: ```cpp #include <string> #include <vector> #include <algorithm> #include <cctype> #include <iostream> using namespace std; class Solution { public: string reverseWords(string s) { // 1. 去除前后空格 trim(s); // 2. 分割单词 vector<string> words = split(s); // 3. 反转单词数组 reverse(words.begin(), words.end()); // 4. 用空格连接单词 string result; for (int i = 0; i < words.size(); i++) { if (i > 0) result += " "; result += words[i]; } return result; } private: // 去除字符串前后的空格(原地操作) void trim(string &s) { if (s.empty()) return; s.erase(0, s.find_first_not_of(" ")); s.erase(s.find_last_not_of(" ") + 1); } // 分割字符串为单词(跳过连续空格) vector<string> split(const string &s) { vector<string> words; int start = 0, end = 0; while (start < s.length()) { // 跳过空格 while (start < s.length() && s[start] == ' ') start++; if (start >= s.length()) break; end = start; // 找到单词的结束位置(下一个空格或字符串末尾) while (end < s.length() && s[end] != ' ') end++; words.push_back(s.substr(start, end - start)); start = end; } return words; } }; int main() { Solution sol; cout << sol.reverseWords("the sky is blue") << endl; // 输出: "blue is sky the" cout << sol.reverseWords(" hello world ") << endl; // 输出: "world hello" cout << sol.reverseWords("a good example") << endl; // 输出: "example good a" return 0; } ``` 注意: - 我们实现了`trim`函数来去除前后空格。 - 分割单词时,我们使用双指针(start和end)来获取每个单词,这样即使有连续空格也能正确分割。 - 使用`vector`存储单词,然后反转整个vector,最后用空格连接。 另一种方法(不使用split,原地反转): 1.反转整个字符串。 2. 然后反转每个单词。 3. 去除多余空格(包括前后空格和中间多余空格)。 但是这种方法比较复杂,而且需要处理空格问题。上面的方法更清晰。 另外,用户要求“不使用atoi”,这里我们并没有用到atoi,所以满足要求。 如果用户要求的是反转每个单词的字母(即引用[3]和引用[4]的方法),那么我们需要调整。但是用户明确说是“单词顺序反转”,所以我们按照整个句子单词顺序反转来实现。 相关问题: 1. 如何用O(1)空间复杂度实现反转字符串中的单词顺序(原地反转)? 2. 如果字符串中有标点符号,反转单词顺序时标点符号应该如何处理? 3. 如何反转每个单词的字母(保持单词顺序不变)? </think>根据引用[1][3]提供的思路,我将介绍两种不使用 `atoi` 实现单词顺序反转的方法。这些方法专注于字符串操作,与数字转换无关,完全符合您的要求。 ### 方法一:分割-反转-拼接(推荐思路) ```cpp #include <vector> #include <string> #include <algorithm> using namespace std; string reverseWords(string s) { // 1. 分割单词 vector<string> words; string word; for (char c : s) { if (c == ' ') { if (!word.empty()) { words.push_back(word); word = ""; } } else { word += c; } } if (!word.empty()) words.push_back(word); // 2. 反转单词顺序 reverse(words.begin(), words.end()); // 3. 拼接结果 string result; for (int i = 0; i < words.size(); ++i) { if (i > 0) result += " "; result += words[i]; } return result; } ``` **算法步骤**: 1. **分割单词**:遍历字符串,遇到非空格字符时构建单词,遇到空格时将完整单词存入数组[^1] 2. **反转顺序**:使用标准库 `reverse` 反转单词数组顺序[^1] 3. **拼接结果**:用空格连接单词形成最终字符串[^1] **时间复杂度**:$O(n)$,空间复杂度:$O(n)$ ### 方法二:双指针原地反转(优化空间) ```cpp string reverseWords(string s) { // 1. 整体反转字符串 reverse(s.begin(), s.end()); // 2. 反转每个单词 int n = s.length(), start = 0, end = 0; while (start < n) { // 跳过空格 while (start < n && s[start] == ' ') start++; end = start; // 定位单词边界 while (end < n && s[end] != ' ') end++; // 反转单个单词 reverse(s.begin() + start, s.begin() + end); start = end; } // 3. 清除多余空格 int idx = 0; for (int i = 0; i < n; i++) { if (s[i] != ' ' || (i > 0 && s[i-1] != ' ')) { s[idx++] = s[i]; } } if (idx > 0 && s[idx-1] == ' ') idx--; return s.substr(0, idx); } ``` **算法步骤**: 1. **整体反转**:先反转整个字符串(`"the sky"` → `"yks eht"`) 2. **单词反转**:对每个单词进行二次反转(`"yks"` → `"sky"`,`"eht"` → `"the"`) 3. **空格处理**:压缩多余空格并修剪首尾空格[^3] **时间复杂度**:$O(n)$,空间复杂度:$O(1)$(原地修改) ### 测试用例 ```cpp cout << reverseWords("the sky is blue") << endl; // "blue is sky the" cout << reverseWords(" hello world ") << endl; // "world hello" cout << reverseWords("a good example") << endl; // "example good a" ``` ### 关键点说明 1. **空格处理**:两种方法均能正确处理前导/尾随空格和连续空格 2. **非字母字符**:可处理带标点的单词(如 `"Let's"` → `"s'teL"`)[^3] 3. **性能对比**: - 方法一更易理解,适合一般场景 - 方法二节省内存,适合大字符串处理 4. **与 `atoi` 无关**:完全基于字符串操作,无需数字转换 这两种方法都严格遵守了您不使用 `atoi` 的要求,专注于纯字符串处理操作实现单词顺序反转
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值