class Solution {
/**
* 反转字符串中的单词顺序
* 步骤:
* 1. 去除首尾及中间多余空格
* 2. 反转整个字符串
* 3. 反转每个单词
*/
public String reverseWords(String s) {
// 1. 去除多余空格
StringBuilder sb = removeExtraSpaces(s);
// 2. 反转整个字符串
reverseString(sb, 0, sb.length() - 1);
// 3. 反转每个单词
reverseEachWord(sb);
return sb.toString();
}
/**
* 去除首尾及中间多余空格
* 优化点:
* - 使用双指针直接在原字符串上遍历,避免多次条件判断
* - 更简洁的空格处理逻辑
*/
private StringBuilder removeExtraSpaces(String s) {
int left = 0;
int right = s.length() - 1;
// 去除首尾空格
while (left <= right && s.charAt(left) == ' ') left++;
while (left <= right && s.charAt(right) == ' ') right--;
StringBuilder sb = new StringBuilder();
while (left <= right) {
char c = s.charAt(left);
// 如果当前字符不是空格,直接添加
if (c != ' ') {
sb.append(c);
}
// 如果当前字符是空格,且前一个字符不是空格(避免连续空格),则添加
else if (sb.charAt(sb.length() - 1) != ' ') {
sb.append(c);
}
left++;
}
return sb;
}
/**
* 反转字符串指定区间 [start, end] 的字符
*/
private void reverseString(StringBuilder sb, int start, int end) {
while (start < end) {
char temp = sb.charAt(start);
sb.setCharAt(start, sb.charAt(end));
sb.setCharAt(end, temp);
start++;
end--;
}
}
/**
* 反转每个单词
* 优化点:
- 直接遍历 StringBuilder,避免额外索引计算
- 更清晰的单词边界处理
*/
private void reverseEachWord(StringBuilder sb) {
int start = 0;
int end = 0;
int n = sb.length();
while (start < n) {
// 找到单词的起始位置
while (start < n && sb.charAt(start) == ' ') start++;
// 找到单词的结束位置
end = start;
while (end < n && sb.charAt(end) != ' ') end++;
// 反转单词,end 停下的位置是单词的下一个字符
reverseString(sb, start, end - 1);
// 移动到下一个单词
start = end;
}
}
}