class Solution {
public:
string trans(string s, int n) {
if (n == 0) return s;
// 第一步:反转整个字符串
reverse(s.begin(), s.end());
// 第二步:反转每个单词并改变大小写
int start = 0;
for (int i = 0; i <= n; i++) {
if (i == n || s[i] == ' ') {
// 反转当前单词
reverseWordAndToggleCase(s, start, i);
start = i + 1;
}
}
return s;
}
private:
void reverseWordAndToggleCase(string& s, int start, int end) {
// 反转单词内部的字符顺序
int left = start, right = end - 1;
while (left < right) {
swap(s[left], s[right]);
// 交换后分别改变大小写
s[left] = toggleCase(s[left]);
s[right] = toggleCase(s[right]);
left++;
right--;
}
// 处理中间字符(当单词长度为奇数时)
if (left == right) {
s[left] = toggleCase(s[left]);
}
}
char toggleCase(char c) {
if (c >= 'a' && c <= 'z') {
return c - 'a' + 'A';
} else if (c >= 'A' && c <= 'Z') {
return c - 'A' + 'a';
}
return c;
}
};
核心思想:
整体反转:先反转整个字符串,这样单词顺序就反了,但每个单词内部的字符顺序也反了
单词内部反转:再反转每个单词内部的字符顺序,恢复单词的正确顺序
大小写反转:在处理每个单词时同时反转字符的大小写
为什么这样处理空格正确:
原字符串开头的空格在整体反转后会跑到结尾
原字符串结尾的空格在整体反转后会跑到开头
单词之间的空格在反转过程中位置保持不变
时间复杂度:O(n)