题目描述
给你一个字符串 s ,逐个翻转字符串中的所有 单词 。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
请你返回一个翻转 s 中单词顺序并用单个空格相连的字符串。
说明:
输入字符串 s 可以在前面、后面或者单词间包含多余的空格。
翻转后单词间应当仅用一个空格分隔。
翻转后的字符串中不应包含额外的空格。
样例描述
示例 1:
输入:s = "the sky is blue"
输出:"blue is sky the"
示例 2:
输入:s = " hello world "
输出:"world hello"
解释:输入字符串可以在前面或者后面包含多余的空格,但是翻转后的字符不能包括。
思路
字符串的常见处理
方法一: 两次翻转
- 难点:以单词为最小单位进行翻转。将这个难点分解为两步如下,
第一步,将整个字符串以字符为单位翻转。
第二步,将每个单词进行翻转。
上面这两步可以互换,是等价的(画图可以看出) - 删空格,从前往后枚举有效空格,将有效的字符放在数组最前面,每次移动都是搜寻一个单词,移动后记得补上1个空格
方法二:双指针 + 一次遍历实现翻转
本方法思路具有跳跃性,不需要真正实现“翻转”。具体如下: - 由于是要反转字符里的单词,可以双指针(指向左右边界)从后往前遍历,不断寻找单词,然后加入到结果集同时加一个分隔空格。循环直到找完所有的或者边界越界。 最后再删除最后一个单词后面的多余空格。 (有点取巧的感觉。。。不过确实牛逼)
- 关键:整个从后往前处理,直接截取单词
上述两种方法都涉及到StringBuffer很多做字符串处理的常用函数
代码
方法一:
class Solution {
public String reverseWords(String s) {
StringBuffer sb = new StringBuffer(s);
int n = s.length();
//用来索引有效字符的下标
int k = 0;
for (int i = 0; i < n; i ++ ) {
//过滤无效空格
if (sb.charAt(i) == ' ') continue;
//先第一步,将每个单词翻转
int j = i, t = k; //t记录单词的第一个字符
//j来确定单词的下标范围,k用来查找单词末尾的字符
while (j < n && sb.charAt(j) != ' ') sb.setCharAt(k ++, sb.charAt(j ++ ));
//翻转单词
reverse(sb, t, k - 1);
//补充一个空格分隔,注意是否越界 超过就不能补
if (k < n) sb.setCharAt(k ++, ' ');
i = j;
}
//如果k前面还有空格,即多加了最后一个单词后的空格,要减一,与后面的空格一起删除
if (sb.charAt(k - 1) == ' ') k --;
sb.delete(k, n);
//第二步,翻转整个字符串 前面删掉了k及后面部分,所以剩余长度到k - 1
reverse(sb, 0, k - 1);
return sb.toString();
}
public void reverse(StringBuffer sb, int l, int r) {
while (l < r) {
char c = sb.charAt(l);
sb.setCharAt(l, sb.charAt(r));
sb.setCharAt(r, c);
l ++;
r --;
}
}
}
方法二:
class Solution {
public String reverseWords(String s) {
int n = s.length();
int left = n - 1, right = n - 1;
StringBuffer res = new StringBuffer();
//左边界没越界时
while (left >= 0) {
//从后往前先找到第一个字符,也就是末尾单词的右边界
while (left >= 0 && s.charAt(left) == ' ') left --;
//如果已经越界,说明不存在了,直接退
if (left < 0) break;
right = left;
//接下来寻找末尾单词的左边界,继续往后找到第一个空格
while (left >= 0 && s.charAt(left) != ' ') left --;
//截取单词放进结果集 [left + 1, right] 注意substring不含右边所以加一
res.append(new StringBuffer(s.substring(left + 1, right + 1)));
//追加分隔空格
res.append(' ');
}
//清除最后一个单词后面的空格
return res.deleteCharAt(res.length() - 1).toString();
}
}