[每日算法] leetcode第151题 Reverse Words in a String

本文详细解析了LeetCode第151题的解题思路及C++实现,要求在O(1)空间复杂度下,反转字符串中的单词顺序,通过多次字符串翻转技巧解决此问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题目描述

Given an input string, reverse the string word by word.

Example:

Input: “the sky is blue”,
Output: “blue is sky the”.

Note:

A word is defined as a sequence of non-space characters. Input string may contain leading or trailing spaces. However, your reversed string should not contain leading or trailing spaces. You need to reduce multiple spaces between two words to a single space in the reversed string.

Follow up: For C programmers, try to solve it in-place in O(1) space.

题目大意

题目意思,很简单,就是把一个字符串中的单词的顺序颠倒过来,其实是相当容易实现的一个问题,采用暴力求解的话,我们可以将该字符串中的每一个单词都拿出来,再做一个逆序排序输出就行了,但是这样实现不够优雅,上面化粗体的"Follow up"要求我们在O(1)的空间复杂度下实现代码,这就规定我们不能使用暴力求解了,因为你需要拿出来,就需要有空间存放,这时的空间复杂度为O(n)。

解题思路

因为要求在O(1)的空间复杂度下实现该题代码,则说明我们可以使用固定的额外空间就实现字符的逆序,其实这个问题可以简化为以下问题:
假设A,B分别是两个字符串,他们以AB的形式构成一个新的字符串,然后我们希望在O(1)的空间复杂度下把他变成BA的形式,应该如何去处理。
关于上面这个问题,我们可以很容易想到字符串的翻转,因为翻转的空间度杂度为O(1),我们只需要一个额外的空间,便可以实现将整个字符串进行翻转。
所以,首先,我们想到的是先把AB翻转一下,得到B’A‘,这里的B’和A‘分别是B和A翻转得到的字符串,这也很容易看出来,由翻转的镜像性。
到这里,你应该也可以很清楚地看出来,我们现在得到了B’A‘,然后目标字符串是BA,很明显,只需要将B’和A‘分别进行一次翻转就可以了。
所以一共经过3次翻转就解决了问题,而字符串的翻转的空间复杂度为O(1)。
然后回到原题,我们可以把原题现在的句子中的word看成我们上题的A和B对待,忽略空格,我们的句子其实就是ABC…,翻转一下便得到…C’B’A’。再依次将每一个word进行翻转便得到了逆序word的句子,这样我们只需要进行n+1次翻转(n为字符串中word的数量),而无论多少次翻转,我们的空间复杂度都为O(1)。

C++代码实现

class Solution {
public:
  void reverseWords(string &s) {
  	// 除去句子中多余空格
  	for (int i = 0; s[i] != 0; i++) {
  		if ((i == 0 && s[i] == ' ') || (s[i] == ' ' && (s[i+1] == ' ' || s[i+1] == 0))) {
  			s.erase(i, 1);
  			i--;
  		}
  	}
  	int len = s.size();

	// 整个字符串翻转
  	for (int i = 0; i < len/2; i++) {
  		swap(s[i], s[len-i-1]);
  	}

	// 对每个word进行翻转
  	int index = 0;
  	for (int i = 0; i <= len; i++) {
  		if (s[i] == ' ' || s[i] == 0) {
  			for (int j = index; j < (i+index)/2; j++) {
  				swap(s[j], s[i-(j-index)-1]);
  			}
  			index = i+1;
  		}
  	}

  }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值