数据结构–翻转字符串里的单词
给你一个字符串 ,请你反转字符串中的单词的顺序。
单词是由非空格字符组成的字符串。且字符串中的单词至少间隔一个空格
返回,单词顺序颠倒,且单词之间用单个空格连接的结果字符串。
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格(即无最前后的空格)。
高科技方法
分析
本来一看就有思路的。但是没想到正则表达式的不在标准库
代码
package String;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class reverseWord {
public static void main(String[] args) {
System.out.println(new reverseWord().test("the sky is blue"));
}
public String test(String s){
// 完成把大于一个的' '替换到只剩一个
String regStr = "(\\x20)+";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(s);
s = matcher.replaceAll("$1");
// 如果第一个字符串前面有空格,就删除它
StringBuilder stringBuilder = new StringBuilder(s);
if (stringBuilder.charAt(0) == ' '){
stringBuilder.deleteCharAt(0);
s = stringBuilder.toString();
}
// 利用空格划分为字符串数组
String [] strings = s.split(" ");
// 完成倒序翻转
StringBuilder endStr = new StringBuilder();
for (int i = strings.length - 1; i >= 0; i--) {
endStr.append(strings[i]);
endStr.append(" ");
}
// 删除最后多加的空格
endStr.deleteCharAt(endStr.length() - 1);
return endStr.toString();
}
}
方法一(菜)
分析
先保留一个空格,然后划分为字符数组,再反向拼接(不必理会)
代码
public String test(String s){
// 通过计数来把超过一个的空格删除掉
int count = 0;
StringBuilder stringBuilder = new StringBuilder(s);
for (int i = 0; i < stringBuilder.length(); i++) {
if (stringBuilder.charAt(i) == ' '){
++count;
}else {
count = 0;
continue;
}
if (count > 1 ){
stringBuilder.deleteCharAt(i--);
}
}
// 把开头的一个空格删除掉
if (stringBuilder.charAt(0) == ' '){
stringBuilder.deleteCharAt(0);
}
// 返回回字符串,然后通过空格划分字符数组
s = stringBuilder.toString();
String[] strings = s.split(" ");
// 反向排序
StringBuilder reverseStr = new StringBuilder();
for (int i = strings.length - 1; i >= 0; --i) {
reverseStr.append(strings[i]);
reverseStr.append(" ");
}
// 删除最后一个多添加的空格
reverseStr.deleteCharAt(reverseStr.length() - 1);
return reverseStr.toString();
}
方法二:数组翻转
分析:
直接通过split方法,按照空格进行分组成字符串数组,这样会有空字符串,通过isEmpty()方法,判断该字符串是否为空,若不为空再进行逆序添加,下面第二个判断目的是为了让第一个添加的是字符串而不是空
代码:
// 方法一;思路:数组的翻转
// 时间复杂度;O(n)
// 空间复杂度:O()
public String reverseWords_1(String s) {
// 按照空格分组
String[] wordArray = s.split(" ");
StringBuffer stringBuffer = new StringBuffer();
int len = wordArray.length;
// len-- 先执行表达式后赋值
// --len 先赋值后执行表达式
while (len-- > 0) {
// 当该字符串不为空时,完成添加(逆序)
if (!wordArray[len].isEmpty()) {
// 因为初始长度为0,但是要求第一位不能是空,所以通过stringBuffer.length() > 0,来满足先添加字符串,再添加空格
// 之后stringBuffer.length() > 0恒成立
if (stringBuffer.length() > 0) {
stringBuffer.append(" ");
}
stringBuffer.append(wordArray[len]);
}
}
return stringBuffer.toString();
}
方法三:双指针
分析
代码
public String reverseWords_2(String s) {
// 删除任何前导和尾随空格。
s = s.trim();
// 字符串长度
int len = s.length();
// 单词起止坐标
int begin = len, end = len;
while (len-- > 0) {
// 遇到非单词分隔的空格符的情况
// 去掉空格符
if (s.charAt(len) == ' ' && begin == end) {
// 新的字符串
s = s.substring(0, len) + s.substring(len + 1, s.length());
begin--;
end--;
// 遇到单词分隔的空格符的情况
} else if (s.charAt(len) == ' ' && begin != end) {
String word = s.substring(begin, end);
s = s.substring(0, len) + (end < s.length() ? s.substring(end, s.length()) : "") + word + " ";
begin--;
end = begin;
// 非空格符的情况,寻找单词起始坐标
} else {
begin--;
}
}
// 处理最后一个单词
String word = s.substring(0, end);
s = s.substring(end, s.length()) + word;
return s;
}
方法四:递归
分析
代码
public String reverseWords_4(String s) {
s = s.trim();
int len = s.length();
while (len-- > 0) {
if (s.charAt(len) == ' ') {
String word = s.substring(len + 1, s.length());
return word + " " + reverseWords(s.substring(0, len));
}
}
return s;
}
方法五:栈
分析
代码
public String reverseWords(String s) {
// 设置一个栈存放单词
Stack<String> stack = new Stack<>();
s.trim();
String[] wordArray = s.split(" ");
for (String word : wordArray) {
if (!word.isEmpty()) {
stack.add(word);
}
}
StringBuffer stringBuffer = new StringBuffer();
while (!stack.isEmpty()) {
stringBuffer.append(stack.pop());
if (!stack.isEmpty()){
stringBuffer.append(" ");
}
}
return stringBuffer.toString();
}