剑指 Offer 58 - I. 翻转单词顺序
一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
1、题目📑
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. ",则输出"student. a am I"。
实例1:
输入: "the sky is blue"
输出: "blue is sky the"
实例2:
输入: " hello world! "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
实例3:
输入: "a good example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
说明:
- 无空格字符构成一个单词。
- 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
- 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
注意:本题与主站 151 题相同:leetcode-cn.com/problems/re…
注意:此题对比原题有改动
2、思路🧠
方法一:java内置类StringBuffer
- 将字符串使用
trim()函数将字符串前后的空格去掉,再进行空格分割处理。 - 需要注意多个空格分隔之后为
""为空的字符串,所以要进行特殊情况的处理。 - 利用
StringBuffer对每个字符串进行去空格拼接,即trim()处理。 - 切记在最后一个单词处理的时候,不进行添加尾部
" "。
方法二:双指针
- 使用
trim()函数将字符串前后的空格去掉 - 使用双指针倒叙遍历字符串,记录该单词的左边界和右边界
- 确定好边界利用字符串自带的函数
substring()截取指定的单词 - 利用 StringBuffer 进行拼接。
这里需要注意的是函数 substring() 是一个左开右闭的区间类似与[1,2)这种形式,所以在考虑截取的时候需要注意单词的前后位置。
废话少说~~~~~上代码!
3、代码👨💻
第一次commit AC
class Solution {
public String reverseWords(String s) {
StringBuffer sb = new StringBuffer();
String str[] = s.trim().split(" ");
for(int i = str.length - 1; i >= 0; i--) {
if(str[i].equals("")) continue;
if(i==0) {
sb.append(str[i].trim());
}else {
sb.append(str[i].trim()).append(" ");
}
}
return sb.toString();
}
}
时间复杂度:O(N) trim() 为O(N),split()为O(N)
空间复杂度:O(N) 快速排序的递归深度平均为 O(logN) ,最差情况为 O(N)。
第二次commit AC
class Solution {
public String reverseWords(String s) {
StringBuffer sb = new StringBuffer();
s = s.trim();
int l = s.length() - 1;
int r = s.length() - 1;
while(l >= 0) {
while(l >=0 && s.charAt(l) != ' ') l--;
sb.append(s.substring(l+1, r+1).trim()).append(" ");
while(l >=0 && s.charAt(l) == ' ') l--;
r = l;
}
return sb.toString().trim();
}
}
时间复杂度:O(N) N 为字符串 s 的长度
空间复杂度:O(N) StringBuffer(Java) 中的字符串总长度 ≤ N
4、总结
该题目对字符串的各种操作API一点要熟悉并且透彻的了解,每一次操作,每一步的过程以及产生的结果。
❤️来自专栏《LeetCode基础算法题》欢迎订阅❤️
厂长写博客目的初衷很简单,希望大家在学习的过程中少走弯路,多学一些东西,对自己有帮助的留下你的赞赞👍或者关注➕都是对我最大的支持,你的关注和点赞给厂长每天更文的动力。
对文章其中一部分不理解,都可以评论区回复我,我们来一起讨论,共同学习,一起进步!