代码随想录算法训练营第八天_第四章_字符串 | 344. 反转字符串、541.反转字符串II、剑指Offer 05.替换空格、151.翻转字符串里的单词、剑指Offer58-II.左旋转字符串

LeetCode344. 反转字符串

题目描述:原地反转字符串s

视频讲解https://www.bilibili.com/video/BV1fV4y17748/?spm_id_from=333.788&vd_source=f98f2942b3c4cafea8907a325fc56a48文章讲解https://programmercarl.com/0344.%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC

  • 思路:
    • 双指针:i 从左到右,j 从右到左
    • 交换 s[i] 和 s[j]
    • i < j:若为奇数个,中间剩一个恰好不用操作
  • 代码:
class Solution {
public:
    void reverseString(vector<char>& s) {
        for (int i = 0, j = s.size() - 1; i < j; ++i, --j) {
            swap(s[i], s[j]);
        }
    }
};

LeetCode541. 反转字符串 II

题目描述:给定字符串s和整数k,反转每2k个字符的前k个。

                剩余字符不足2k个,则反转前k个;不足k个,则全部反转。

视频讲解https://www.bilibili.com/video/BV1dT411j7NN/?spm_id_from=333.788&vd_source=f98f2942b3c4cafea8907a325fc56a48文章讲解https://programmercarl.com/0541.%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2II.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC

  • 思路:
    • 用 i 扫描字符串 s,一次走 2k 步
    • 够 k 个,反转 [i, i + k)
    • 不够 k 个,反转 [i, s.size())
  • 代码:
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;
            }
            // 剩余字符不足k个,全部反转
            reverse(s.begin() + i, s.end());
        }
        return s;
    }
};

剑指Offer 05.替换空格

题目描述:把字符串 s 中的每个空格替换成"%20"

文章讲解https://programmercarl.com/%E5%89%91%E6%8C%87Offer05.%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC

  • 思路:
    • 统计空格数,扩充
    • 双指针:i 扫新字符串,j 扫原字符串,从后往前赋值
    • i 追上 j,则空格均已替换
  • 代码:
class Solution {
public:
    string replaceSpace(string s) {
        int sOldSize = s.size();
        // 统计空格数
        int count = 0;
        for (int i = 0; i < sOldSize; ++i) {
            if (s[i] == ' ') {
                ++count;
            }
        }
        // 扩充字符串
        s.resize(sOldSize + count * 2);
        int sNewSize = s.size();
        for (int i = sNewSize - 1, j = sOldSize - 1; j < i; --i, --j) {
            if (s[j] != ' ') {
                s[i] = s[j];
            } else {
                s[i] = '0';
                s[i - 1] = '2';
                s[i - 2] = '%';
                i -= 2;
            }
        }
        return s;
    }
};

LeetCode151.翻转字符串里的单词

题目描述:反转字符串s中 单词 的顺序。

注意:输入字符串 s中可能会存在前导空格尾随空格或者单词间的多个空格

返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

视频讲解https://www.bilibili.com/video/BV1uT41177fX文章讲解https://programmercarl.com/0151.%E7%BF%BB%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC

  • 思路:                                            " the              sky            is           blue "
    • 删除多余空格:                      "the sky is blue"
      • 双指针:fast 扫描原串,slow 作为新串下标
      • fast 寻找非空格元素(每个单词的首字母)
      • 找到后先给 slow 放置空格(第一个单词除外)
      • 再移动整个单词,直到遇到空格,进入下一轮循环
    • 反转整个字符串:                  "eulb si yks eht"
    • 反转每个单词:                      "blue is sky the"
  • 代码:
class Solution {
public:
    // 删除多余空格
    void removeExtraSpaces(string& s) {
        // 双指针
        // slow作为新串下标
        int slow = 0;
        // fast扫描原串,寻找需要移到新串的字符
        for (int fast = 0; fast < s.size(); ++fast) {
            if (s[fast] != ' ') {
                // 在单词前放一个空格(第一个除外)
                if (slow != 0) {
                    s[slow++] = ' ';
                }
                // 把整个单词移过去
                while(fast < s.size() && s[fast] != ' ') {
                    s[slow++] = s[fast++];
                }
            }
        }
        s.resize(slow);
    }
    string reverseWords(string s) {
        // 删除多余空格
        removeExtraSpaces(s);
        // 反转整个字符串
        reverse(s.begin(), s.end());
        // 反转每个单词
        int start = 0;
        for (int i = 0; i <= s.size(); ++i) {
            // i扫到单词结束位置
            if (i == s.size() || s[i] == ' ') {
                // 反转[start, i)
                reverse(s.begin() + start, s.begin() + i);
                // 更新start至下一个单词的起始位置
                start = i + 1;
            }
        }
        return s;
    }
};

剑指Offer58-II.左旋转字符串

题目描述:把字符串前面的若干个字符转移到字符串的尾部。

文章讲解https://programmercarl.com/%E5%89%91%E6%8C%87Offer58-II.%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC

  • 思路:
    • 反转 [0, n)
    • 反转 [n, s.size())
    • 反转 整个字符串
  • 代码:
class Solution {
public:
    string reverseLeftWords(string s, int n) {
        // 原地操作
        // 反转 [0 , n)
        reverse(s.begin(), s.begin() + n);
        // 反转 [n, s.size())
        reverse(s.begin() + n, s.end());
        // 反转整个字符串
        reverse(s.begin(), s.end());
        return s;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值