题目描
输入一个英文句子,翻转句子的单词顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字符一样处理。
例如,“student. a am I”。正确的输出应该是“I am a student.”。
牛客上输入的是字符串,输出也是字符串。
一种解题思路,也是offer书上的,先翻转整个字符串,再对每个单词翻转。也有利用栈来完成翻转过程的解法。对于空格的处理也会出现新的解法。
java涉及到字符串操作的可以分成两类,String和(StringBuilder、StringBuffer)两类。因此,选取不同的类的写法不同。可以调用StringBuffer的函数来完成。
解法1:
使用最原始的方法,两次翻转,并且所有操作自己来。也是书上的写法。先翻转整个字符串,并用两个指针变量记录某个单词的首尾,去寻找空格,当尾部碰到空格,就说明现在记录的范围内的单词需要再翻转,翻转过后,重新维护两个指针。
public class Solution { public String ReverseSentence(String str) { if (str == null || str.length() == 0) return str; char[] arr = str.toCharArray();//转换成字符数组 reverse(arr, 0, arr.length - 1);//先全部翻转一次 int start = 0;//指向单词第一个字母 int end = 0;//指向单词最后一个字母 while (start < arr.length) { if (arr[start] == ' ') { //如果start指向的是空格,就换下一个,因为指针要指向的是单词。 start++; end++; } else if (end == arr.length || arr[end] == ' ') { //要么尾部是空格,要么end刚刚超过数组最后一个角标,这两种情况就应该翻转了 //end之所以会超过最后角标,是因为当最后一个字符不是空格时,会让end++,所以会越界 reverse(arr, start, end-1); //翻转后,应该重新记录下个单词,因此更新end和start。 end++; start = end;//这句和上一句可以写成start = ++end; } else { //到这里就说明,start指的不是空格,end也指的不是空格,说明是正常单词,end++即可 end++; } } return String.valueOf(arr); } private void reverse(char[] arr, int begin, int end){ while(begin<end){ char temp = arr[begin]; arr[begin] = arr[end]; arr[end] = temp; begin++; end--; } } }
解法2:
在调用一些其他库函数来解决问题时,其实是思想偷懒了,让更多的细节让底层自己去实现。所以某些时候会降低效率,考试推荐使用解法1。平常解决问题时怎么舒服怎么来。
public class Solution { public String ReverseSentence(String str) { StringBuffer sb = new StringBuffer(""); if(str.length() <= 0 || str.trim().equals("")){//需要将多个空格的情况考虑进来 return str; } String[] strSet = str.split(" ");//将一个字符串分成多个后,装数组里,效率没解法1高 int length = strSet.length; for(int i = length-1; i > 0 ;i--){ sb.append(strSet[i]+" ");//从尾部添加就可以保证顺序颠倒了 } sb.append(strSet[0]);//写在外面是因为最后一个添加的不用添加空格了。 return sb.toString(); } }
解法3:
拓宽视野用
import java.util.Stack; public class Solution { public String ReverseSentence(String str) { if(str == null || str.length()==0) return str; StringBuilder res = new StringBuilder(); String[] tmp = str.split(" ");//按照空格,将当前一个字符串分成多个字符串 if(tmp.length==0)//为了防止出现全空格的情况 return str; Stack<String> stack = new Stack<>(); for(int i=0; i<tmp.length-1; i++) { stack.push(tmp[i]);//将整个小字符串都压入栈 stack.push(" ");//然后加上空格 } stack.push(tmp[tmp.length-1]);//最后一个直接添加,后面不用再加空格 while(!stack.isEmpty()) {//最后一个都添加了就的准备弹出了。 res.append(stack.pop()); } return res.toString(); } }
总结:还有使用栈的思路,也还蛮有意思的。不过最好能给出较优解,尽量少使用一些库函数,平常做题开阔视野就可以了。