算法与数据结构(十三):字符串反转题型总结

字符串反转总结

字符串反转(如 “hello world” 转变为 “world hello”)作为一种常见题型,如果利用 python 作很简单,但是用 C++ 做往往需要考虑旋转、平移等策略,比较麻烦,这里对此类题型做一个小结。

Leetcode 151. Reverse Words in a String

CategoryDifficultyLikesDislikes
algorithmsMedium (17.15%)6032338

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

CategoryDifficultyLikesDislikes
algorithmsEasy (64.59%)65569

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 --;
        }
        
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值