剑指offer 44. 翻转单词序列

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)

思路二和思路三均参考自:https://leetcode-cn.com/problems/fan-zhuan-dan-ci-shun-xu-lcof/solution/mian-shi-ti-58-i-fan-zhuan-dan-ci-shun-xu-shuang-z/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值