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)