44. 翻转单词序列
题目描述
牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
思路一:
用空格分割字符串后用StringBuilder变量从后往前遍历数组拼接
注意点:要用trim() 方法去除前后导空格, 并且单词之间可能有多个空格,所以必须使用正则表达式来分割,单纯的使用空格分割后面添加的时候必须判断是否是空串
1 class Solution { 2 public String reverseWords(String s) { 3 if(s == null || s.trim().length() == 0){ 4 return ""; 5 } 6 // 用空格分割成数组,空格可能有很多个,所以要用正则表达式 7 String[] splits = s.trim().split("[ ]+"); 8 // 使用StringBilder进行拼接 9 StringBuilder sb = new StringBuilder(""); 10 for(int i = splits.length - 1; i >= 0; i--){ 11 sb.append(splits[i]); 12 if(i > 0){ 13 sb.append(" "); 14 } 15 } 16 return sb.toString(); 17 } 18 }
leetcode 运行时间为8 ms - 16.63%, 空间为39.3 MB - 14.95%
复杂度分析:
时间复杂度:split()函数的时间复杂度为O(n), 一次遍历数组的时间复杂度为O(n), 所以总的时间复杂度为O(n)
空间复杂度:需要一个额外的数组来存放单词,所以空间复杂度为O(n),倒序可以使用栈来实现,不过那样会增加一个O(n)的空间复杂度
思路二:
在使用split()函数分割字符串时仍然使用空格,而非正则表达式,因为正则表达式效率比较低,但是在append()到结果字符串时要判断是否是空串,是则跳过
1 class Solution { 2 public String reverseWords(String s) { 3 if(s == null || s.trim().length() == 0){ 4 return ""; 5 } 6 // 用空格分割成数组,空格可能有很多个,所以要用正则表达式 7 String[] splits = s.trim().split(" "); 8 // 使用StringBilder进行拼接 9 StringBuilder sb = new StringBuilder(""); 10 for(int i = splits.length - 1; i >= 0; i--){ 11 if("".equals(splits[i])){ 12 continue; 13 } 14 sb.append(splits[i]); 15 if(i > 0){ 16 sb.append(" "); 17 } 18 } 19 return sb.toString(); 20 } 21 }
leetcode 执行用时:1 ms - 100.00%, 空间为 38.9 MB - 57.82%,可以看到,运行时间短了很多
复杂度分析:
时间复杂度:split()函数的时间复杂度为O(n), 一次遍历数组的时间复杂度为O(n), 所以总的时间复杂度为O(n)
空间复杂度:需要一个额外的数组来存放单词,所以空间复杂度为O(n),倒序可以使用栈来实现,不过那样会增加一个O(n)的空间复杂度
思路三:
不使用split()函数,从后往前倒着遍历,获取到单词就添加到结果字符串中
1 class Solution { 2 public String reverseWords(String s) { 3 if(s == null || s.trim().length() == 0){ 4 return ""; 5 } 6 s = s.trim(); 7 // 两个指针,i 和 j, 初始时都在末尾 8 int i = s.length() - 1, j = i; 9 StringBuilder sb = new StringBuilder(""); 10 while(i >= 0){ 11 // 让i指针向前查找,查找到但此前的第一个空格 12 while(i >= 0 && s.charAt(i) != ' '){ 13 i--; 14 } 15 // 截取[i+1, j+1)的子串到sb 16 sb.append(s.substring(i+1, j+1) + " "); 17 18 // 跳过单词间多余的空格 19 while(i >= 0 && s.charAt(i) == ' '){ 20 i--; 21 } 22 j = i; 23 } 24 return sb.toString().trim(); 25 } 26 }
leetcode 执行用时:3 ms - 65.01%, 空间为:39.2 MB - 16.37%
复杂度分析:
时间复杂度:遍历了一遍字符串,所以时间复杂度为O(n)
空间复杂度:O(1)