Leetcode刷题-151:颠倒字符串中的单词

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”
解释:如果两个单词间有多余的空格,颠倒后的字符串需要将单词间的空格减少到仅有一个。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-words-in-a-string

2.题目分析

2.1 整体思路描述

按照题意,要求我们进行的其实是两个工作,其一是去除字符串中不规则的空格字符,不规则的定义就是空格重复或者首尾的空格。其二就是进行字符串中每个单词的倒置,注意这里提到的是单词的倒置,单词内的字符顺序需要保持先后的一致性。这似乎是有点复杂的,但其实我们可以将其进行两次倒置。采取负负得正的效果将单词进行倒置。

对上述的倒置思路我们给出一个例子。假设有字符串" hello world "我们需要进行单词的倒置,我们就可以将其分为两个步骤,我们首先将整个字符串进行倒置,这时就变成了"dlrow olleh",此时我们只需要在对这个字符串中的每个单词进行局部的倒置就可以完成题目要求达到修改字符串为"world hello"

似乎此时解题步骤已经出来了,那就是下面三个步骤

  1. 不规则空格去除
  2. 字符串倒置
  3. 字符串内局部单词倒置

我们只需要按照上述步骤编码就可以了,其实上述三个不走的先后顺序是可以随意调换的,这对最后结果是没有影响的。但是在操作的时候对于字符串的操作是需要比较仔细的,因为很容易就会出错。

2.2 实施

2.2.1 去除不规则空格

我们在去除字符串的不规则空格时一般会想到使用string自带的erase函数,我们这里来看一下erase函数的使用规则

形式 说明
string& erase (size_t pos = 0, size_t len = npos) 删除从pos开始的len个字符
iterator erase (const_iterator p); 删除迭代器p指向的元素
iterator erase (const_iterator first, const_iterator last) 删除[first,last)范围的元素

利用上面的erase函数的话我们就可以采用一次循环,在遍历到重复空格时进行重复值的删除。但是使用这个形式的话我们会发现首尾的单个空格去除需要额外处理,为了方便起见,在实现时我选择将首尾位置的空格放在循环外单独处理。

在本题中使用erase函数其实效率比较低,因为erase本身就是一个O(N)的操作,所以我们当然可以尝试通过其他方法进行优化,我们前面了解过,在处理数组类似的数据结构时如果使用双指针可以达到**复杂度降重**的效果。在本题中我们亦可以以双指针的思想进行不规则空格去除。具体思想类似前面的题目中的27_移除元素。我们对其思想进行一个基本的描述

  • 定义快慢指针遍历字符串,初始化快慢指针为首位置,fast作为工作指针,slow作为赋值指针。
  • 以快指针fast作为工作指针循环遍历,当快指针遍历到一个空格,则说明这是单词之间的分隔,不是单词的内容,所以此时fast指针继续向前移动直到遇到一个非空格字符,而slow指针则不动。
  • 如果fast指向的不为空,说明要处理一个新的单词了,所以给slow赋值一个空格作为分隔然后移动slow指针,然后将fast的值赋值给slow的值,slowfast同时移动
  • 去重部分代码如下:
			if(s[fast] != ' '){
   
                if(slow !=0 ) s[slow++]=' ';
                while(fast<s.size() && s[fast]!=' '){
   
                    s[slow++]=s[fast++]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值