力扣 151 颠倒字符串中的单词 中等 Java
文章目录
题目链接
https://leetcode-cn.com/problems/reverse-words-in-a-string/
1、题目要求
给你一个字符串 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"
解释:如果两个单词间有多余的空格,颠倒后的字符串需要将单词间的空格减少到仅有一个。
2、思路分析
在 Java 中 String 类型是不可变的,为了线程安全,可以构建字符串常量池以及可以作为 HashMap 中的 key 的使用;
在操作字符串的时候,可以使用 charAt() 函数将字符串中的每一个字符取出来使用,可以在操作的使用定义 left right 两个数组索引,或者理解成为操作数据的两个指针对于这个字符串数组进行操作;
假设原始字符串:" hello world "
1、将字符串中的左侧的空格过滤,右侧的空格过滤,以及字符串中间的空格过滤;
此时得到:"hello world"
2、将多余空格过滤好的字符串整体的进行翻转
此时得到:"dlrow olleh"
3、对于字符串中的每一个单词进行翻转,其翻转单词的划分就是字符串中的 ‘ ’ ;
此时得到:"world hello"
3、执行代码 Java
class Solution {
public String reverseWords(String s) {
// 将字符串头部 尾部 以及中间的字符进行消除
StringBuilder sb = trimString(s);
// 将整个字符串进行翻转
reverse(sb, 0, sb.length() - 1);
// 将字符串里面的单个字符逐个翻转
reverseWord(sb);
return sb.toString();
}
public StringBuilder trimString(String str) {
StringBuilder sb = new StringBuilder();
int left = 0;
int right = str.length() - 1;
while (left < right & str.charAt(left) == ' ') {
++left;
}
while (left < right & str.charAt(right) == ' ') {
--right;
}
while (left <= right) {
char temp = str.charAt(left);
if (temp != ' ') {
sb.append(temp);
} else {
// == ' '就说明新建的 StringBuilder 中间已经存在 ' '了,不需要再次放进去一个 ' ';
if (sb.charAt(sb.length() - 1) != ' ') {
sb.append(temp);
}
}
++left;
}
return sb;
}
public void reverse(StringBuilder sb, int start, int end) {
while (start < end) {
char temp = sb.charAt(start);
sb.setCharAt(start, sb.charAt(end));
sb.setCharAt(end, temp);
start++;
end--;
}
}
// public void reverseEachWord(StringBuilder sb) {
// int n = sb.length();
// int start = 0, end = 0;
// while (start < n) {
// // 循环至单个单词的末尾
// while (end < n && sb.charAt(end) != ' ') {
// ++end;
// }
// // 翻转单词
// reverse(sb, start, end - 1);
// // 更新start,去找下一个单词
// start = end + 1;
// ++end;
// }
// }
public void reverseWord(StringBuilder sb) {
int start = 0;
int end = 0;
int n = sb.length();
while (start < n) {
// 按照 ‘ ’ 取出来中间所有的单词
while (end < n && sb.charAt(end) != ' ') {
++end;
}
// 循环出来调用转换
reverse(sb,start,end - 1);
// start 和 end 存在于同一个起跑线上面
start = end + 1;
++end;
}
}
}
4、问题反思
4.1、& && 之间的区别
&& 是短路运算符号 可以提高算法的效率在一定程度上面
4.2、循环出来的 end 多加了 1 在后面转换的额时候,需要减去 1
4.3 ++ – 那些事儿
i++; ++i;
1、单独使用的时候没有区别都是自己增加 1 ;
2、 但是放在表达式中含义不一样,在计算机底层的操作不一样,可以查看汇编语言确定;
a = ++i; a = i++; 这两个不一样的,因为在表达式里面,不是单独使用的;
3、 第三种情况就是放置在数组中的情况;
arr[index++] 等同于 arr[index]; index++; 两句代码
5、时间复杂度以及空间复杂度分析
时间复杂度:O(n)O(n),其中 nn 为输入字符串的长度。
下面的两层 while 循环中 第二层循环只有单词的长度的次数,没有进行全部的遍历,所以时间复杂度还是O(n);
空间复杂度:Java 需要 O(n) 的空间来存储字符串
6、小结
通过基于双指针法的进行字符串单词的倒转,体会到了字符串的拼接,多个方法的联合使用以及方法互相之间的参数传递;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!