力扣151.翻转字符串里的单词

翻转字符串里的单词题目

使用额外空间的方法

最先想到的方法是遍历字符串,将最终结果储存到结果字符串中。
因为每个单词的顺序都要翻转,所以从字符串的末尾开始向前遍历。由于是逆序遍历,为了保持每个单词不被改变,使用栈存储每个单词的字母,再输出后就可以恢复正常顺序。
对于冗余的空格,在遇到时只需将其出栈即可。

class Solution {
public:
    string reverseWords(string s) {
        stack<char> word_stack;		// 储存每个单词
        string result;
        int i = s.length();
        // 从字符串末端开始遍历
        while (i-- > 0) {
        	// 将每个字符入栈
            word_stack.push(s[i]);
            // 如果遇到空格
            if (s[i] == ' ') {
            	// 将空格出栈
                word_stack.pop();
                // 此时如果栈中有单词
                if (!word_stack.empty()) {
                	// 将单词拼接到结果字符串中
                    while (!word_stack.empty()) {
                        result += word_stack.top();
                        word_stack.pop();
                    }
                    // 每个单词后加上空格
                    result += " ";
                }
            }
        }
        // 此时result是以空格结尾
        // 若栈中没有单词了,则删掉空格
        if (word_stack.empty()) {
            result.erase(result.end() - 1);
        }
        // 否则拼接最后一个单词
        else {
            while (!word_stack.empty()) {
                result += word_stack.top();
                word_stack.pop();
            }
        }
        return result;
    }
};

字符串中的每个字符都执行了入栈和出栈两次操作,因此时间复杂度的 O ( n ) O(n) O(n),而由于额外使用了栈和结果字符串,空间复杂度也为 O ( n ) O(n) O(n)

空间复杂度为O(1)的方法

但题目中说可以尝试空间复杂度为 O ( 1 ) O(1) O(1)的方法。
不使用额外的辅助空间就需要原地翻转字符串。

对于一个字符串,要达到题目要求的翻转结果,可以翻转两次:

  • 首先整体翻转,如:hello world → dlrow olleh
  • 然后每个单词各自翻转,如:dlrow olleh → world hello

而对于冗余的空格,可以将字符串向左压缩。使用双指针,快指针遇到冗余空格则跳过,否则将其挪到慢指针的位置。最后慢指针之后的字符都是冗余的,使用resize()将其抛弃。

class Solution {
public:
    // 翻转函数
    void reverse(string& s, int left, int right) {
        char temp;
        while (left < right) {
            temp = s[left];
            s[left] = s[right];
            s[right] = temp;
            left++; right--;
        }
    }
    string reverseWords(string s) {
        // 利用双指针去除冗余空格
        int slow = 0, fast = 0;
        // 去除前面的空格
        while (s[fast] == ' ')
            fast++;
        // 去掉单词间的冗余空格
        s[slow++] = s[fast++];  //先赋第一个字符以省去边界判断
        while (fast < s.length()) {
            if (s[fast] != ' ' || (s[fast] == ' ' && s[fast - 1] != ' ') )
                s[slow++] = s[fast];
            fast++;
        }
        // 重置字符串大小
        s.resize(slow);
        if (s[s.length() - 1] == ' ')
            s.pop_back();

        // 第一次翻转
        reverse(s, 0, s.length() - 1);
        // 第二次翻转
        slow = 0;   fast = 0;
        while (fast < s.length()) {
            while (fast < s.length() && s[fast] != ' ')
                fast++;
            reverse(s, slow, fast - 1);
            fast++;
            slow = fast;
        }
        return s;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值