题目描述
给定一个字符串,请将字符串中单词的顺序倒过来。
注意:
- 单词是指连续非空格字符;
- 单词之间可能包含多余空格,请在结果中删除多余空格,使得单词之间仅包含一个空格;
- 请删除字符串首尾多余的空格;
进一步:能否只使用额外 $O(1)$ 的空间?
样例
输入:"the sky is blue",
输出:"blue is sky the".
算法
(数组翻转) $O(n)$
分两步操作:
- 将字符串中的每个单词逆序,样例输入变为:
"eht yks si eulb"
; - 将整个字符串逆序,样例输入变为:
"blue is sky the"
;
时间复杂度分析:整个字符串总共扫描两遍,所以时间复杂度是 $O(n)$。且每次翻转一个字符串时,可以用两个指针分别从两端往中间扫描,每次交换两个指针对应的字符,所以额外空间的复杂度是 $O(1)$。
C++ 代码
class Solution {
public:
string reverseWords(string s) {
int k = 0;
for (int i = 0; i < s.size();)
{
int j = i;
while (j < s.size() && s[j] == ' ') j ++ ;
if (j == s.size()) break;
i = j;
while (j < s.size() && s[j] != ' ') j ++ ;
reverse(s.begin() + i, s.begin() + j);
if (k) s[k ++ ] = ' ';
while (i < j) s[k ++ ] = s[i ++ ];
}
s.erase(s.begin() + k, s.end());
reverse(s.begin(), s.end());
return s;
}
};
这下看懂了orz
如果不写erase的话,输出会奇奇怪怪的,貌似不只是删除结尾的空格(小心翼翼)
另外一种跳过空字符的方法可以原地实现吗?试了下只想到要开个用来返回的空间的方法
上面的做法可以跳过空白字符呀,你说的是哪种算法呀。
用y总的思路实现了一个自己的版本
reverse函数很慢,y总的代码更快一点,自己处理前面和后面的空格。
要实现原地修改是不是得语言支持修改字符串?对于不能修改字符串的语言,就实现不了原地修改?
对滴,如果输入的字符数组不能被修改,那就需要返回一个新数组了,就不能用原地修改了。
用c的stringstream能自动解决空格问题,或者python语言的 x = s.strip(” “).split() return ” “.join(x[::-1]) 也有自动去空格的现成的函数。不过用c手动去空格确实很锻炼思维。
对滴,C++比较蛋疼,字符串处理的内置函数比较少。不过既然作为练习,锻炼一下思维比较好。
像java 没有reverse函数,也适合这样做么?
没有reverse函数的话,可以手写呀,一个循环就可以实现。
s.erase(s.begin() + k, s.end());这是什么操作
是删除最后面一个空格吗
单词之间可能包含多余空格,做翻转时会将多余空格去掉,所以每个单词可能会向前移动,最后需要把多余的部分删掉。
1
如果原始的字符串是”abcd”前后都没有空格,那么在s.erase(s.begin() + k, s.end())的时候不会出错吗?
不会,while(i < j) 这句就会把k带到s. end () 上,最后k总能移动到尾部,你可以动手模拟一下
对滴,
k
最终一定小于等于字符串总长度,所以不会出错的~大佬,为什么同样的代码run以后会这样报错啊
solution.cpp: In member function helper
Line 26: Char 43: error: conversion from ‘void’ to non-scalar type ‘std::__cxx11::string’ {aka ‘std::__cxx11::basic_string[HTML_REMOVED]‘} requested
我试了一下,发现是因为leetcode把这道题目的函数返回值和参数改了。
上面的代码已更新,现在可以在leetcode上通过了。