文章目录
- 题目
- 补充知识
- ArrayList动态数组
- StringBuilder类
- 解
- ①穷举法
- ②穷举法改进
- ③双指针
题目
给你一个字符串 s
,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s
中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
**注意:**输入字符串 s
中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
示例 1:
输入:s = "the sky is blue"
输出:"blue is sky the"
示例 2:
输入:s = " hello world "
输出:"world hello"
解释:反转后的字符串中不能存在前导空格和尾随空格。
补充知识
ArrayList动态数组
ArrayList的基本使用方式:
-
导入ArrayList类:
import java.util.ArrayList;
-
创建ArrayList对象:
ArrayList<String> list = new ArrayList<>();
-
添加元素到ArrayList中:
list.add("Element1");
-
获取ArrayList中的元素:
String element = list.get(index);
-
修改ArrayList中的元素:
list.set(index, newValue);
-
删除ArrayList中的元素:
list.remove(index);
-
获取ArrayList的大小:
int size = list.size();
-
检查ArrayList是否为空:
boolean isEmpty = list.isEmpty();
-
遍历ArrayList:
-
使用for循环:
for (int i = 0; i < list.size(); i++) {String element = list.get(i); }
-
使用增强型for循环:
for (String element : list) {}
-
-
检查ArrayList是否包含某个元素:
boolean containsElement = list.contains("Element1");
-
清空ArrayList:
list.clear();
-
转换为数组:
String[] array = list.toArray(new String[0]);
StringBuilder类
常用方法:
-
append(): 在字符串构建器的末尾追加字符串、字符或其他数据。
StringBuilder sb = new StringBuilder(); sb.append("Hello"); sb.append(" "); sb.append("world");
-
insert(): 在指定位置插入字符串、字符或其他数据。
StringBuilder sb = new StringBuilder("Hello world"); sb.insert(5, ", "); // Hello, world
-
delete(): 删除从指定位置开始到指定位置结束之间的字符(前闭后开,包括开始位置不包括结束位置)。
StringBuilder sb = new StringBuilder("Hello world"); sb.delete(5, 11); // 删除 " world" 变成 "Hello"
-
deleteCharAt(): 删除指定位置的字符。
StringBuilder sb = new StringBuilder("Hello world"); sb.deleteCharAt(5); // 删除空格
-
replace(): 用指定字符串替换从指定开始索引到指定结束索引之间的字符。
StringBuilder sb = new StringBuilder("Hello world"); sb.replace(6, 11, "Java"); // 替换 "world" 为 "Java"
-
substring(): 返回从指定开始索引到指定结束索引之间的子字符串。
StringBuilder sb = new StringBuilder("Hello world"); String sub = sb.substring(6, 11); // 获取 "world"
-
reverse(): 反转字符串。
StringBuilder sb = new StringBuilder("Hello"); sb.reverse(); // 变为 "olleH"
-
charAt(): 返回指定索引处的字符。
cStringBuilder sb = new StringBuilder("Hello"); char c = sb.charAt(1); // 获取索引为1的字符 'e'
-
length(): 返回字符串的长度。
StringBuilder sb = new StringBuilder("Hello"); int length = sb.length(); // 返回5
-
indexOf() / lastIndexOf(): 返回指定字符串或字符在字符串构建器中第一次出现的索引或最后一次出现的索引。
StringBuilder sb = new StringBuilder("Hello world"); int index1 = sb.indexOf("o"); // 返回4 int index2 = sb.lastIndexOf("o"); // 返回7
-
toString(): 将字符串构建器转换为普通的字符串。
StringBuilder sb = new StringBuilder("Hello world"); String str = sb.toString(); // 返回 "Hello world"
解
①穷举法
11ms,超过11%
设置了一个动态数组,遍历s,判断当前元素和上一个元素是否为空
上一个元素为空,当前不是空的时候,记录单词的起始位置
上一个元素不为空,当前为空的时候,将单词加入到动态数组当中
如果是s的最后一个元素,需要判断是否是空格,如果不是空格的话,要将最后一个单词加入到动态数组
最后倒着遍历整个动态数组,存入到字符串end
import java.util.ArrayList;
class Solution {public String reverseWords(String s) {boolean cur=false;boolean last=true;//上一个是否是空String end=new String();int start=0;ArrayList<String> strs=new ArrayList<String>();for(int i=0;i<s.length();i++){char element=s.charAt(i);cur=(element==' ')?true:false;last=(i!=0 && s.charAt(i-1)==' ')?true:false;if(last && !cur){//如果上一个是空格,当前不是空格//则记录开始的位置start=i;}if(i!=0 && !last && cur){//如果上一个不是空格,这一个是空格String str=s.substring(start,i);strs.add(str);}if(i==s.length()-1 && !cur){// 如果是最后一个,也要考虑一下最后一个不是空格的情况~String str=s.substring(start,i+1);strs.add(str);} }System.out.print(strs.get(0)+"/");for(int i=strs.size()-1;i>=0;i--){end+=strs.get(i);if(i!=0){end+=" ";}}return end;}
}
②穷举法改进
7ms,超过42.8%
①当中的end从String类型改成StringBuilder类型
import java.util.ArrayList;
class Solution {public String reverseWords(String s) {boolean cur=false;boolean last=true;//上一个是否是空StringBuilder end=new StringBuilder();int start=0;ArrayList<String> strs=new ArrayList<String>();for(int i=0;i<s.length();i++){char element=s.charAt(i);cur=(element==' ')?true:false;last=(i!=0 && s.charAt(i-1)==' ')?true:false;if(last && !cur){//如果上一个是空格,当前不是空格//则记录开始的位置start=i;}if(i!=0 && !last && cur){//如果上一个不是空格,这一个是空格String str=s.substring(start,i);strs.add(str);}if(i==s.length()-1 && !cur){// 如果是最后一个,也要考虑一下最后一个不是空格的情况~String str=s.substring(start,i+1);strs.add(str);} }for(int i=strs.size()-1;i>=0;i--){end.append(strs.get(i));if(i!=0){end.append(" ");}}return end.toString();}
}
③双指针
4ms,81.48%
参考leetcode-Krahets
通过string类的trim函数可以去除字符串的首尾空格,主要是没有想到用while的方式完成代码,实际上①②都有点类似双指针的解法,都是找到了单词的首尾,然后进行记录,当前代码和之前不同的地方在于没有使用动态数组,直接将单词保存在StringBuilder当中,并且采用的是从后向前读取,不需要考虑翻转问题。(直接保存到StringBuilder是个挺好的想法,本来想尝试修改②的代码,突然发现是正序的,如果修改的话会比较麻烦,遂放弃)
import java.util.ArrayList;
class Solution {public String reverseWords(String s) {s=s.trim();//去除首尾空格StringBuilder strs=new StringBuilder();int j=s.length()-1,i=j;//初始ij都在字符串末尾的地方while(i>=0){while(i>=0 && s.charAt(i)!=' ') i--;//跳过不是空格的元素strs.append(s.substring(i+1,j+1)+" ");//遇到空格,则添加元素到strs,按照题目要求单词之间空格隔开while(i>=0 && s.charAt(i)==' ') i--;//跳过两个单词之间的空格j=i;//定位到下一个单词的末尾处}return strs.toString().trim();//添加元素的时候,每个元素后面都增加了" ",这里需要删除一下 }
}