问题
给定一个字符串,逐个翻转字符串中的每个单词
说明:
- 无空格字符构成一个单词
- 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括
如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个
示例 1:
输入:”the sky is blue”
输出:”blue is sky the”
示例 2:
输入:” hello world! “
输出:”world! hello”
解释:输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括
示例 3:
输入:”a good example”
输出:”example good a”
解释:如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个
示例 4:
输入:s = “ Bob Loves Alice “
输出:”Alice Loves Bob”
示例 5:
输入:s = “Alice does not even like bob”
输出:”bob like even not does Alice”
方法一:Java语言特性
class Solution {public String reverseWords(String s) {// trim() 方法用于删除字符串的头尾空白符s = s.trim();// 正则匹配连续的空白字符作为分隔符分割// List<String>不能直接实例化/**split("\\s+")按空格、制表符等进行拆分(也就是说它是按空白部分进行拆分,不管这个空白使用什么 操作留下的,提如空格键 tab键)split(" +") 按空格进行拆分(也就是说只有按空格键流出来的空白才会是拆分的一句)\\s表示 空格,回车,换行等空白符,+号表示一个或多个的意思*/List<String> wordList = Arrays.asList(s.split("\\s+")); // 将数组转化成list集合/**sd@sdd@sdddsplit("@")[sd,sdd,sddd]*/Collections.reverse(wordList);return String.join(" ", wordList);}}
时间复杂度:
,其中 N 为输入字符串的长度
空间复杂度:
,用来存储字符串分割之后的结果
方法二
class Solution {public String reverseWords(String s) {StringBuilder sb = trimSpaces(s);// 翻转字符串reverse(sb, 0, sb.length() - 1);// 翻转每个单词reverseEachWord(sb);return sb.toString();}public StringBuilder trimSpaces(String s) {int left = 0, 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;}public void reverse(StringBuilder sb, int left, int right) {while (left < right) {char tmp = sb.charAt(left);//setCharAt(int index,Char ch),第一个参数是取代的位置索引从0开始,第二个参数是你要替换 为的字符串sb.setCharAt(left++, sb.charAt(right));sb.setCharAt(right--, tmp);}}public void reverseEachWord(StringBuilder sb) {int n = sb.length();int start = 0, end = 0;while (start < n) {// 循环至单词的末尾while (end < n && sb.charAt(end) != ' ') {++end;}// 翻转单词reverse(sb, start, end - 1);// 更新start,去找下一个单词start = end + 1;++end;}}}
时间复杂度:
,其中 N 为输入字符串的长度
空间复杂度:
,N 为存储字符串的长度
方法三:双端队列
由于双端队列支持从队列头部插入的方法,因此我们可以沿着字符串一个一个单词处理,然后将单词压入队列的头部,再将队列转成字符串即可
class Solution {
public String reverseWords(String s) {
int left = 0, right = s.length() - 1;
// 去掉字符串开头的空白字符
while (left <= right && s.charAt(left) == ' ') {
++left;
}
// 去掉字符串末尾的空白字符
while (left <= right && s.charAt(right) == ' ') {
--right;
}
Deque<String> d = new ArrayDeque<String>();
StringBuilder word = new StringBuilder();
while (left <= right) {
char c = s.charAt(left);
if ((word.length() != 0) && (c == ' ')) {
// 将单词 push 到队列的头部
d.offerFirst(word.toString());
word.setLength(0);
} else if (c != ' ') {
word.append(c);
}
++left;
}
d.offerFirst(word.toString());
return String.join(" ", d);
}
}
