问题描述

给定一个由多个单词组成的句子,每个单词由大小写字母混合构成,单词间使用单个空格分隔。要求输出最后一个单词的长度

约束条件:

  • 每个单词非空
  • 总字符长度不超过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)

只使用了常数个额外变量

优点:

  1. 高效:只需要一次遍历
  2. 节省空间:不需要额外存储
  3. 鲁棒性好:能处理末尾有空格的情况

解法二:使用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;
}

算法特点

优点:

  1. 代码简洁易读
  2. 自动处理多余空格
  3. 容易扩展(如需要处理所有单词)

缺点:

  1. 需要额外的字符串拷贝
  2. 使用stringstream有额外开销
  3. 需要存储最后一个单词的完整副本

解法四:双指针法

#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,访问越界

总结

获取字符串最后一个单词的长度是一个基础的字符串处理问题,但它涉及了许多重要的编程概念:

  1. 字符串遍历技巧:从后向前遍历是解决此类问题的关键
  2. 边界条件处理:空字符串、空格、单个单词等情况都需要考虑
  3. 算法选择:根据具体需求选择最合适的算法
  4. 代码鲁棒性:处理各种异常输入情况

推荐方法:从后向前遍历法

  • 效率高,空间复杂度低
  • 代码清晰,易于理解
  • 鲁棒性好,能处理各种边界情况

掌握这个问题的解法不仅能帮助解决类似问题,还能提高字符串处理的基本功。在实际开发中,根据具体场景选择最合适的方法才是最重要的。

以上就是C++获取字符串最后一个单词长度的多种方法的详细内容,更多关于C++获取字符串最后单词长度的资料请关注本站其它相关文章!

声明:本站(华域联盟www.cnhackhy.com)所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。