【数据结构和算法】反转字符串中的单词

简介: 给你一个字符串s,请你反转字符串中单词的顺序。单词是由非空格字符组成的字符串。s中使用至少一个空格将字符串中的单词分隔开。返回单词顺序颠倒且单词之间用单个空格连接的结果字符串。注意:输入字符串s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

其他系列文章导航

Java基础合集

数据结构与算法合集

设计模式合集

多线程合集

分布式合集

ES合集


文章目录

其他系列文章导航

文章目录

前言

一、题目描述

二、题解

2.1 方法一:双指针

2.2 方法二:分割 + 倒序

三、代码

3.1 方法一:双指针

3.2 方法二:分割 + 倒序

四、复杂度分析

4.1 方法一:双指针

4.2 方法二:分割 + 倒序


前言

这是力扣的151题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的两种。


一、题目描述

给你一个字符串 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"

解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。


提示:

    • 1 <= s.length <= 104
    • s 包含英文大小写字母、数字和空格 ' '
    • s至少存在一个 单词

    进阶:如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用 O(1) 额外空间复杂度的 原地 解法。


    二、题解

    2.1 方法一:双指针

    思路与算法:

      • 先去首尾空格。
      • 倒序遍历字符串 s ,记录单词左右索引边界 i , j 。
      • 每确定一个单词的边界,则将其添加至单词列表 res 。
      • 最终,将单词列表拼接为字符串,去掉尾部空格,并返回即可。

      2.2 方法二:分割 + 倒序

      思路与算法:

      以空格为分割符完成字符串分割后,若两单词间有 x>1 个空格,则在单词列表 strs 中,此两单词间会多出 x−1 个 “空单词” (即 "" )。

      解决方法:倒序遍历单词列表,并将单词逐个添加至 StringBuilder ,遇到空单词时跳过。


      三、代码

      3.1 方法一:双指针

      Java版本:

      class Solution {
          public String reverseWords(String s) {
              s = s.trim();                                          // 删除首尾空格
              int j = s.length() - 1, i = j;
              StringBuilder res = new StringBuilder();
              while (i >= 0) {
                  while (i >= 0 && s.charAt(i) != ' ') i--;          // 搜索首个空格
                  res.append(s.substring(i + 1, j + 1)).append(" "); // 添加单词
                  while (i >= 0 && s.charAt(i) == ' ') i--;          // 跳过单词间空格
                  j = i;                                             // j 指向下个单词的尾字符
              }
              return res.toString().trim();                          // 转化为字符串并返回
          }
      }

      image.gif

      Python版本:

      class Solution:
          def reverseWords(self, s: str) -> str:
              s = s.strip()                            # 删除首尾空格
              i = j = len(s) - 1
              res = []
              while i >= 0:
                  while i >= 0 and s[i] != ' ': i -= 1 # 搜索首个空格
                  res.append(s[i + 1: j + 1])          # 添加单词
                  while i >= 0 and s[i] == ' ': i -= 1 # 跳过单词间空格
                  j = i                                # j 指向下个单词的尾字符
              return ' '.join(res)                     # 拼接并返回

      image.gif

      3.2 方法二:分割 + 倒序

      Java版本:

      class Solution {
          public String reverseWords(String s) {
              String[] split = s.trim().split(" ");
              StringBuilder res = new StringBuilder();
              for (int i = split.length - 1; i >= 0; i--) {
                  if (!split[i].equals("")) {
                      res.append(split[i]).append(" ");
                  }
              }
              return res.toString().trim();
          }
      }

      image.gif

      Python版本:

      class Solution:
          def reverseWords(self, s: str) -> str:
              return ' '.join(s.strip().split()[::-1])

      image.gif


      四、复杂度分析

      4.1 方法一:双指针

        • 时间复杂度 O(N) : 其中 N 为字符串 s 的长度,线性遍历字符串。
        • 空间复杂度 O(N) : 新建的 list(Python) 或 StringBuilder(Java) 中的字符串总长度 ≤ N ,占用 O(N) 大小的额外空间。

        4.2 方法二:分割 + 倒序

          • 时间复杂度 O(N) : 总体为线性时间复杂度,各函数时间复杂度和参考资料链接如下。
            • split() 方法: 为 O(N) 。
            • trim() 和 strip() 方法: 最差情况下(当字符串全为空格时),为 O(N) 。
            • join() 方法: 为 O(N) 。
            • reverse() 方法: 为 O(N) 。
              • 空间复杂度 O(N) : 单词列表 strs 占用线性大小的额外空间。
              目录
              相关文章
              |
              1月前
              |
              存储 人工智能 算法
              数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
              这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
              79 3
              数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
              |
              17天前
              |
              缓存 算法 Java
              本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
              在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
              36 6
              |
              1月前
              |
              存储 算法 Java
              Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性
              Java Set因其“无重复”特性在集合框架中独树一帜。本文解析了Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性,并提供了最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的hashCode()与equals()方法。
              35 4
              |
              1月前
              |
              搜索推荐 算法
              数据结构与算法学习十四:常用排序算法总结和对比
              关于常用排序算法的总结和对比,包括稳定性、内排序、外排序、时间复杂度和空间复杂度等术语的解释。
              21 0
              数据结构与算法学习十四:常用排序算法总结和对比
              |
              1月前
              |
              机器学习/深度学习 搜索推荐 算法
              探索数据结构:初入算法之经典排序算法
              探索数据结构:初入算法之经典排序算法
              |
              1月前
              |
              算法 Java 索引
              数据结构与算法学习十五:常用查找算法介绍,线性排序、二分查找(折半查找)算法、差值查找算法、斐波那契(黄金分割法)查找算法
              四种常用的查找算法:顺序查找、二分查找(折半查找)、插值查找和斐波那契查找,并提供了Java语言的实现代码和测试结果。
              22 0
              |
              1月前
              |
              算法 安全 数据安全/隐私保护
              基于game-based算法的动态频谱访问matlab仿真
              本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
              |
              9天前
              |
              算法 数据安全/隐私保护 索引
              OFDM系统PAPR算法的MATLAB仿真,对比SLM,PTS以及CAF,对比不同傅里叶变换长度
              本项目展示了在MATLAB 2022a环境下,通过选择映射(SLM)与相位截断星座图(PTS)技术有效降低OFDM系统中PAPR的算法实现。包括无水印的算法运行效果预览、核心程序及详尽的中文注释,附带操作步骤视频,适合研究与教学使用。
              |
              17天前
              |
              算法 数据挖掘 数据安全/隐私保护
              基于FCM模糊聚类算法的图像分割matlab仿真
              本项目展示了基于模糊C均值(FCM)算法的图像分割技术。算法运行效果良好,无水印。使用MATLAB 2022a开发,提供完整代码及中文注释,附带操作步骤视频。FCM算法通过隶属度矩阵和聚类中心矩阵实现图像分割,适用于灰度和彩色图像,广泛应用于医学影像、遥感图像等领域。
              |
              18天前
              |
              算法 调度
              基于遗传模拟退火混合优化算法的车间作业最优调度matlab仿真,输出甘特图
              车间作业调度问题(JSSP)通过遗传算法(GA)和模拟退火算法(SA)优化多个作业在并行工作中心上的加工顺序和时间,以最小化总完成时间和机器闲置时间。MATLAB2022a版本运行测试,展示了有效性和可行性。核心程序采用作业列表表示法,结合遗传操作和模拟退火过程,提高算法性能。
              下一篇
              无影云桌面