【LeetCode】151. 翻转字符串里的单词(剑指offer 58-I)

151. 翻转字符串里的单词

知识点:字符串;双指针

题目描述

给你一个字符串 s ,逐个翻转字符串中的所有 单词 。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

请你返回一个翻转 s 中单词顺序并用单个空格相连的字符串。

说明:

输入字符串 s 可以在前面、后面或者单词间包含多余的空格。
翻转后单词间应当仅用一个空格分隔。
翻转后的字符串中不应包含额外的空格

示例
输入:s = "the sky is blue" 输出:"blue is sky the" 输入:s = "  hello world  " 输出:"world hello" 解释:输入字符串可以在前面或者后面包含多余的空格,但是翻转后的字符不能包括。

解法一:调用API

要对字符串,包括集合里的常用方法很熟悉,这样就可以直接调用里面的常用方法,比如说去掉首尾空格,比如说以某个字符分割,比方说以某个字符连接,比方说反转;

class Solution { public String reverseWords(String s) { //利用API; s = s.trim(); String[] str = s.split("\\s+"); //正则表达式,根据一个或多个空格分割; List<String> list = new ArrayList<>(); for(String i : str){ list.add(i); //将字符串加入列表; } Collections.reverse(list); //直接调用反转方法; return String.join(" ", list); //字符串常用方法,以空格连接,返回一个字符串; } }

时间复杂度:O(N);
空间复杂度:O(N);

解法二:手写方法

我们上面主要使用了两个方法:去掉空格,反转;所以我们需要手动实现这两个方法;

  1. 去掉首尾两边和中间的多余空格;
  2. 将整个字符串反转;
  3. 将字符串里单个字符再反转;
    需要注意的是,在java里字符串是不可变量,所以需要将其转化为可变的数据结构,比如数组;
class Solution { public String reverseWords(String s) { StringBuilder sb = trimSpaces(s); reverse(sb, 0, sb.length()-1); reverseWord(sb); return sb.toString(); } //去掉首尾和多余空格; private StringBuilder trimSpaces(String s){ int left = 0, right = s.length()-1; while(left <= right && s.charAt(left) == ' '){ left++; } //去掉左侧空格,定位到左侧第一个无空格处; while(left <= right && s.charAt(right) == ' '){ right--; } //同理去掉右侧空格; StringBuilder sb = new StringBuilder(); while(left <= right){ char c = s.charAt(left); if(c != ' ') sb.append(c); //到这证明遇到空格了,这时候看sb里最后一个不是空格就给加进去; else if(sb.charAt(sb.length()-1) != ' ') sb.append(c); left++; } return sb; } //反转整个字符; private void reverse(StringBuilder sb, int front, int tail){ while(front < tail){ char temp = sb.charAt(front); //注意StringBuilder底层是数组, //但是没有sb[front];获取指定索引就用charAt,包括String也是; sb.setCharAt(front, sb.charAt(tail)); sb.setCharAt(tail, temp); front++; tail--; } } //反转单个单词; private void reverseWord(StringBuilder sb){ int start = 0, end = 0; //end记录每个单词的最后; int l = sb.length(); while(start < l){ while(end < l && sb.charAt(end) != ' '){ end++; } //end指定空格处; reverse(sb, start, end-1); start = end+1; //更新为下一个单词首处; end++; } } }

时间复杂度:O(N);
空间复杂度:O(N);

解法三:双指针

先把首尾空格去掉,然后定义两个指着,从后往前,分别指向每个单词的首和尾,再加入StringBuilder里;

class Solution { public String reverseWords(String s) { s = s.trim(); //去掉首尾空格; StringBuilder sb = new StringBuilder(); int i = s.length()-1, j = i; //两个指着一个指向单词开头,一个指向结尾; while(i >= 0){ while (i >= 0 && s.charAt(i) !=' ') i--; //i停在空格上; sb.append(s.substring(i+1, j+1)+' '); //前开后闭;添加单词; while (i >= 0 && s.charAt(i) == ' ') i--; //跳过空格; j = i; //j指向下一个单词的尾; } return sb.toString().trim(); //因为上面在每个单词后面都加了空格,所以把最后的结尾的删除; } }

时间复杂度:O(N);
空间复杂度:O(N);

体会

  • 要知道字符串的特点:在java语言中是不可变性。所以只要是需要修改字符串就需要引入新的可变的数据结构,常用StringBuilder。
  • 要对String、StringBuilder常用方法熟悉;能想到。

相关链接

翻转字符串里单词
[剑指offer58-I 翻转单词顺序](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/


__EOF__

本文作者Curryxin
本文链接https://www.cnblogs.com/Curryxin/p/15041994.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Curryxin  阅读(84)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
Live2D
欢迎阅读『【LeetCode】151. 翻转字符串里的单词(剑指offer 58-I)』
点击右上角即可分享
微信分享提示