问题描述
给定一个由多个单词组成的句子,每个单词由大小写字母混合构成,单词间使用单个空格分隔。要求输出最后一个单词的长度。
约束条件:
- 每个单词非空
- 总字符长度不超过 103103
- 单词间使用单个空格分隔
示例:
输入:hellonowcoder 输出:13 输入:a b c d 输出:1
解法一:从后向前遍历法(推荐)
#include <iostream>
#include <string>
using namespace std;
int main() {
string str;
getline(cin, str);
int len = 0;
int i = str.size() - 1;
// 跳过末尾可能的空格(虽然题目说没有,但增加鲁棒性)
while (i >= 0 && str[i] == ' ') i--;
// 计算最后一个单词的长度
while (i >= 0 && str[i] != ' ') {
len++;
i--;
}
cout << len << endl;
return 0;
}算法分析
时间复杂度: o(n)
最坏情况下需要遍历整个字符串
空间复杂度: o(1)
只使用了常数个额外变量
优点:
- 高效:只需要一次遍历
- 节省空间:不需要额外存储
- 鲁棒性好:能处理末尾有空格的情况
解法二:使用rfind方法
#include <iostream>
#include <string>
using namespace std;
int main() {
string str;
getline(cin, str);
// 从后向前查找最后一个空格的位置
size_t pos = str.rfind(' ');
if (pos == string::npos) {
// 没有空格,整个字符串就是一个单词
cout << str.size() << endl;
} else {
// 计算最后一个单词的长度
cout << str.size() - pos - 1 << endl;
}
return 0;
}关键点说明
rfind(' '): 从字符串末尾开始查找空格string::npos: 表示未找到,值为-1(但类型为size_t,所以是最大无符号数)- 注意处理只有一个单词的情况
解法三:使用stringstream分割
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main() {
string str;
getline(cin, str);
stringstream ss(str);
string word, last_word;
// 读取所有单词,最后一个存储在last_word中
while (ss >> word) {
last_word = word;
}
cout << last_word.size() << endl;
return 0;
}算法特点
优点:
- 代码简洁易读
- 自动处理多余空格
- 容易扩展(如需要处理所有单词)
缺点:
- 需要额外的字符串拷贝
- 使用stringstream有额外开销
- 需要存储最后一个单词的完整副本
解法四:双指针法
#include <iostream>
#include <string>
using namespace std;
int main() {
string str;
getline(cin, str);
int right = str.size() - 1;
// 右指针:跳过末尾空格
while (right >= 0 && str[right] == ' ') right--;
int left = right;
// 左指针:找到单词开头
while (left >= 0 && str[left] != ' ') left--;
// 计算长度
cout << right - left << endl;
return 0;
}算法性能对比
| 方法 | 时间复杂度 | 空间复杂度 | 优点 | 缺点 |
|---|---|---|---|---|
| 从后向前遍历 | o(n) | o(1) | 效率高,内存少 | 需要手动处理边界 |
| rfind方法 | o(n) | o(1) | 代码简洁 | 需要处理npos |
| stringstream | o(n) | o(n) | 自动处理空格 | 额外开销大 |
| 双指针法 | o(n) | o(1) | 思路清晰 | 需要两个指针 |
边界条件处理
1. 空字符串
// 在从后向前遍历法中
if (str.empty()) {
cout << 0 << endl;
return 0;
}2. 全是空格
// 在从后向前遍历法中,第一个while循环后i可能为-1
if (i < 0) {
cout << 0 << endl;
return 0;
}3. 末尾有多个空格
// 所有方法都应该处理这种情况 // 解法一和四已经通过while循环处理
扩展问题
1. 获取倒数第二个单词的长度
#include <iostream>
#include <string>
using namespace std;
int main() {
string str;
getline(cin, str);
int count = 0;
int i = str.size() - 1;
// 跳过末尾空格
while (i >= 0 && str[i] == ' ') i--;
// 找倒数第一个单词
while (i >= 0 && str[i] != ' ') i--;
// 跳过单词间的空格
while (i >= 0 && str[i] == ' ') i--;
// 找倒数第二个单词的末尾
int end = i;
while (i >= 0 && str[i] != ' ') i--;
cout << end - i << endl;
return 0;
}2. 统计句子中单词的数量
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main() {
string str;
getline(cin, str);
stringstream ss(str);
string word;
int count = 0;
while (ss >> word) {
count++;
}
cout << count << endl;
return 0;
}3. 获取最长的单词
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main() {
string str;
getline(cin, str);
stringstream ss(str);
string word, longest_word;
int max_len = 0;
while (ss >> word) {
if (word.size() > max_len) {
max_len = word.size();
longest_word = word;
}
}
cout << "最长单词: " << longest_word << ", 长度: " << max_len << endl;
return 0;
}实际应用场景
1. 命令行工具
// 实现类似linux的wc命令,统计单词数 // 可以扩展为获取最后一行或最后一个单词
2. 文本编辑器
// 在代码编辑器中,获取光标所在单词的长度 // 用于自动补全或语法高亮
3. 日志分析
// 分析日志文件的最后一个状态码或错误信息
4. 自然语言处理
// 在nlp预处理中,获取句子的最后一个词 // 用于语言模型训练或情感分析
测试用例
void test() {
// 测试用例集合
vector<pair<string, int>> test_cases = {
{"hellonowcoder", 13},
{"a b c d", 1},
{"hello world", 5},
{"a", 1},
{" ", 0}, // 全是空格
{"hello ", 5}, // 末尾有空格
{" hello", 5}, // 开头有空格
{"multiple spaces between", 7}, // 多个空格
{"", 0}, // 空字符串
{"12345 67890", 5},
{"the quick brown fox jumps over the lazy dog", 3}
};
for (auto& test_case : test_cases) {
// 测试各个算法
cout << "输入: \"" << test_case.first << "\", 期望: " << test_case.second << endl;
}
}优化技巧
1. 使用引用避免拷贝
// 在处理大字符串时,使用const引用
void processstring(const string& str) {
// 处理逻辑
}2. 预分配内存
// 如果知道最大长度,可以预分配 str.reserve(1000); // 根据题目约束
3. 使用c风格字符串
// 在性能关键场景,可以使用c风格字符串
int getlastwordlength(const char* str) {
int len = 0;
int i = strlen(str) - 1;
while (i >= 0 && str[i] == ' ') i--;
while (i >= 0 && str[i] != ' ') {
len++;
i--;
}
return len;
}常见错误
1. 忘记处理npos
// 错误示例
size_t pos = str.rfind(' ');
int length = str.size() - pos - 1; // 当pos为npos时,计算错误2. 未考虑末尾空格
// 错误示例
int pos = str.rfind(' ');
if (pos != -1) {
cout << str.size() - pos - 1 << endl; // 如果末尾有空格,结果错误
}3. 越界访问
// 错误示例 int i = str.size() - 1; while (str[i] == ' ') i--; // 如果字符串为空,i为-1,访问越界
总结
获取字符串最后一个单词的长度是一个基础的字符串处理问题,但它涉及了许多重要的编程概念:
- 字符串遍历技巧:从后向前遍历是解决此类问题的关键
- 边界条件处理:空字符串、空格、单个单词等情况都需要考虑
- 算法选择:根据具体需求选择最合适的算法
- 代码鲁棒性:处理各种异常输入情况
推荐方法:从后向前遍历法
- 效率高,空间复杂度低
- 代码清晰,易于理解
- 鲁棒性好,能处理各种边界情况
掌握这个问题的解法不仅能帮助解决类似问题,还能提高字符串处理的基本功。在实际开发中,根据具体场景选择最合适的方法才是最重要的。
以上就是c++获取字符串最后一个单词长度的多种方法的详细内容,更多关于c++获取字符串最后单词长度的资料请关注代码网其它相关文章!
发表评论