一、题目
给你一个字符串 s
,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s
中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s
中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
示例 1:
输入:s = "the sky is blue" 输出:"blue is sky the"
示例 2:
输入:s = " hello world " 输出:"world hello" 解释:反转后的字符串中不能存在前导空格和尾随空格。
示例 3:
输入:s = "a good example" 输出:"example good a" 解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。
二、思路
刚开始看这题就觉得挺难的。如果调用库函数还能解决,如果不调用库函数就有些麻烦。
最终选择了一种比较容易理解的方法:先去除字符串多余的空格。再反转整个字符串,再反转各个单词。代码中有个人注释,希望能帮助到大家,欢迎指出理解错误的地方!
三、代码
第一种方法:调用库函数
针对split函数的解释:
需要注意的是,split(" ") 会将连续的空格视为多个分隔符,并且会生成空字符串作为结果数组中的元素。这意味着如果输入字符串中有多个连续的空格,split(" ") 会生成一些空字符串。
例如,对于输入字符串 "a good example",使用 split(" ") 会得到以下数组:
String[ ] str = {"a", "good", "", "", "example"};
所以加入了if判断。
class Solution {
public String reverseWords(String s) {
//用split函数分割出所有的单词
String[] str = s.split(" ");
StringBuilder sb = new StringBuilder();
for (int i = str.length - 1; i >= 0; i--) {
if (str[i].length() > 0) {
sb.append(str[i]).append(" ");
}
}
return sb.toString().trim(); //去除尾部的空格
}
}
第二种方法:
class Solution {
public String reverseWords(String s) {
//1.先去除多余空格
StringBuilder sb = removeSpace(s);
//2.反转整个字符串
reverse(sb,0,sb.length() - 1);
//3.反转每个单词
reverseWord(sb);
return sb.toString();
}
public StringBuilder removeSpace(String s){
//1.首先找到第一个字符和最后一个字符,去除首尾空格
int start = 0;
int end = s.length() - 1;
while(s.charAt(start) == ' ') start++;
while(s.charAt(end) == ' ') end--;
//2.用StringBuilder拼接
StringBuilder sb = new StringBuilder();
while(start <= end) {
char c = s.charAt(start);
//第二个条件需要理解,是为了不拼接连续的空格
//当c为字母时,直接拼接,若c为空格,就需要考虑已经拼接的字符串
//如果字符串末尾是空格,就不能拼接空格c,避免出现多个空格。
//不是空格说明到达了一个单词的结尾,需加入空格
if(c != ' ' || sb.charAt(sb.length() - 1) !=' ') {
sb.append(c);
}
start++;
}
return sb;
}
public void reverse(StringBuilder sb,int start, int end){
//双指针进行反转,这里用到setCharAt函数,
//或者直接调用reverse函数
while(start <= end) {
char temp = sb.charAt(start);
sb.setCharAt(start,sb.charAt(end));
sb.setCharAt(end,temp);
start++;
end--;
}
}
public void reverseWord(StringBuilder sb){
//反转单词
int start = 0;
int end = 1;
int n = sb.length();
while(start < n) {
while (end < n && sb.charAt(end) != ' ') { //找到单词的末尾后的空格
end++;
}
reverse(sb, start, end - 1); //反转该单词
start = end + 1; //跳过空格
end = start + 1; //找下一个单词
}
}
}