Leetcode——344. 反转字符串/541. 反转字符串 II/151. 颠倒字符串中的单词/剑指 Offer 58 - II. 左旋转字符串

概述

344. 反转字符串

541. 反转字符串 II

151. 颠倒字符串中的单词

剑指 Offer 58 - II. 左旋转字符串

  • 这几题都和字符串翻转有关

分析

344

  • 题目要求原地修改,可以考虑使用双指针+swap()函数实现

    实际上,内置函数reverse()就是通过这个实现;

541

  • 这题,我们利用reverse()模拟一下操作即可

151

  • 个人认为这是一个技巧题,要能想到使用多次反转的思路
    • 首先翻转整个字符串
    • 然后在对每个单词进行一次翻转,即可实现最终效果

这里有一个难点在于,第二次翻转如何确定一个单词进行翻转

**剑指 Offer 58 **

  • 这题,个人认为也算一个技巧题,和151一样,使用多次翻转的思路

思路

151

第二次翻转如何确定一个单词?

  • 我们容易想到利用空格来区分单词,但是根据题目说明:存在前导空格、尾随空格和单词间多个空格,所以这里还是需要仔细处理一下
  • 首先我们第一翻转后,题目中的三种特殊空格情况仍然存在,我们可以分情况处理:
    • 对于前导空格和单词间的多个空格,我们可以每次确定一个字母后,再去寻找该字母所在的单词
    • 而通常也是利用空格来区分单词。但是考虑到末尾可能不存在空格,就无法区分最后一个单词,于是为了统一操作,我们可以在末尾手动添加一个空格

代码

344

class Solution {
public:
    void reverseString(vector<char>& s) {
        int left = 0, right = s.size() - 1;		// 双指针
        while (left < right) {
            swap(s[left++], s[right--]);		// STL swap()        
        }
    }
};

541

class Solution {
public:
    string reverseStr(string s, int k) {
        for (int i = 0; i < s.size();i += (2 * k)) {		// 模拟操作
            if (i + k <= s.size()) {
                reverse(s.begin() + i, s.begin() + i + k );
                continue;
            }
            reverse(s.begin() + i, s.begin() + s.size());
        }
        return s;
    }
};

151

class Solution {
public:
    string reverseWords(string s) {
        reverse(s.begin(), s.end());        // 先翻转所有字符

        s.push_back(' ');       // 统一操作,在末尾添加空格
        for(int i = 0; i < s.size(); ++i) {
            if (s[i] != ' ') {		// 直到出现第一个字母,可以处理前导空格和单词间多个空格
                int j = i + 1;
                for (; j < s.size(); ++j) {
                    if (s[j] == ' ') {		// 遇到一个空格,可以确定该单词的前后位置索引了
                        reverse(s.begin() + i, s.begin() + j);      // 再翻转单个单词
                        i = j;  		// 继续处理  
                        break;			
                    }
                }
            }
        }
        // 去除多余空格。利用双指针法,向前移动
        int i = 0, j = 0;
        for(;j < s.size(); ++j) {
            if (s[j] != ' ')
                s[i++] = s[j];
            else if(s[j] == ' ' && i > 0 && s[i - 1] != ' ')
                s[i++] = ' ';

        }
        s.resize(i - 1);     // 缩小string,留下实际有用的部分
        return s;
    }
};

小技巧:

直接利用resize()来删除末尾的内存

剑指 Offer 58

class Solution {
public:
    string reverseLeftWords(string s, int n) {
        reverse(s.begin(), s.end());		// 第一次翻转整个字符串

        int size = s.size();
        // 下面两个翻转是为了恢复正常的顺序,如果不懂可以手动模拟一下
        reverse(s.begin(), s.begin() + size - n);	
        reverse(s.begin() + size - n, s.end());

        return s;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值