字符串反转总结
字符串反转(如 “hello world” 转变为 “world hello”)作为一种常见题型,如果利用 python 作很简单,但是用 C++ 做往往需要考虑旋转、平移等策略,比较麻烦,这里对此类题型做一个小结。
Leetcode 151. Reverse Words in a String
Category | Difficulty | Likes | Dislikes |
---|---|---|---|
algorithms | Medium (17.15%) | 603 | 2338 |
Given an input string, reverse the string word by word.
Example 1:
Input: "the sky is blue"
Output: "blue is sky the"
Example 2:
Input: " hello world! "
Output: "world! hello"
Explanation: Your reversed string should not contain leading or trailing spaces.
Example 3:
Input: "a good example"
Output: "example good a"
Explanation: You need to reduce multiple spaces between two words to a single space in the reversed string.
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) extra space.
解题思路(时间复杂度 O(n),空间复杂度 O(n)):
这道题难点不在于反转,难点在于消除单词前后以及单词之间多余的空格,其最终结果要求前后无空格,中间只保留一个空格,因此,若想采用空间复杂度为 O(1) 的三次旋转(先对单词进行反转,再最后来一次总的反转),后面还得多一个去除多余空格的处理流程,这个后面再说,先说一下时空复杂度都为 O(n) 的简便处理方式。
对于时间复杂度 O(n) 与空间复杂度 O(n) 的解法很容易理解,直接构建一个新的字符串,将原来字符串直接阶段做反向拼接即可得到结果:
代码如下:
class Solution {
public:
string reverseWords(string s) {
string res;
int begin = 0;
for (int i = 0; i < s.size(); ++i) {
if (s[i] == ' ') {
if (i > begin) res = s.substr(begin, i - begin) + " " + res;
begin = i + 1;
}
else if (i == s.size() - 1) res = s.substr(begin, s.size() - begin) + " " + res;
}
s = res.substr(0, res.size() - 1);
return s;
}
};
注:上面代码中 if (i > begin)
是精华所在,其保证前后无空格,中间最多一个空格;
对应 Python 版本:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
class Solution(object):
def reverseWords(self, s):
return " ".join(s.split()[::-1])
LeetCode 186. Reverse Words in a String II
Given an input string, reverse the string word by word. A word is defined as a sequence of non-space characters. The input string does not contain leading or trailing spaces and the words are always separated by a single space.
Example 1:
Given s = "the sky is blue",
return "blue is sky the".
Note: Could you do it in-place without allocating extra space?
解题思路(时间复杂度O(n),空间复杂度 O(1)):
该题假设开头和结尾没有空格,而且单词之间只有一个空格。是上一道题的简化版,所以可以直接采用三次旋转得到,先将单词反转,再将整体反转;也可以先整天反转再单词反转,代码如下:
class Solution {
public:
void reverseWords(string &s) {
int left = 0;
for (int i = 0; i <= s.size(); ++i) {
if (i == s.size() || s[i] == ' ') {
reverse(s, left, i - 1);
left = i + 1;
}
}
reverse(s, 0, s.size() - 1);
}
void reverse(string &s, int left, int right) {
while (left < right) {
swap(s[left], s[right])
++left; --right;
}
}
};
LeetCode 557. Reverse Words in a String III
Category | Difficulty | Likes | Dislikes |
---|---|---|---|
algorithms | Easy (64.59%) | 655 | 69 |
Given a string, you need to reverse the order of characters in each word within a sentence while still preserving whitespace and initial word order.
Example 1:
Input: "Let's take LeetCode contest"
Output: "s'teL ekat edoCteeL tsetnoc"
Note: In the string, each word is separated by single space and there will not be any extra space in the string.
解题思路(时间复杂度 O(n),空间复杂度 O(1)):
这道题比较简单,连三次反转都用不了, 直接对 word 进行反转即可,代码如下:
*
* [557] Reverse Words in a String III
*/
class Solution {
public:
string reverseWords(string s) {
int length = s.size();
int left = 0, right = 0;
while (right < length) {
if (s[right] == ' ') {
swapCore(s, left, right - 1);
left = right + 1;
}
else if (right == length - 1) {
swapCore(s, left, right);
break;
}
right ++;
}
return s;
}
void swapCore(string& s, int left, int right) {
while (left < right)
{
swap(s[left], s[right]);
left ++;
right --;
}
}
};