随想录一刷Day08——字符串

Day08_字符串

1. 反转字符串

344. 反转字符串
思路:

首位交换

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

2. 反转字符串 II

541. 反转字符串 II
思路:

字符串反转的区间是[i * 2 * k, i * 2 * k + k),遍历所有的反转区间,将字母首尾反转即可。

class Solution {
public:
    string reverseStr(string s, int k) {
        int s_len = s.length();
        for (int i = 0; i*2*k < s_len; i++) {
            int left = i * 2 * k;
            int right = left + k - 1;
            if (right >= s_len) right = s_len - 1;
            while (left < right) {
                char temp = s[left];
                s[left++] = s[right];
                s[right--] = temp;
            }
        }
        return s;
    }
};

3. 替换空格

剑指 Offer 05. 替换空格
思路:

方法一:
空间换时间,再开一个额外的字符串空间,存放答案。

class Solution {
public:
    string replaceSpace(string s) {
        int s_len = s.length();
        string ans = "";
        for (int i = 0; i < s_len; ++i) {
            if (s[i] != ' ') ans += s[i];
            else ans += "%20";
        }
        return ans;
    }
};

方法二:
不开额外空间,提前算好替换后需要的总的数组空间大小,将字符串数组扩充。
从扩充后的数组尾部开始,利用双指针,从右向左遍历字符串,将字符依次移动到扩充后空间的相应位置。
这样的时间复杂度为 O ( n ) O(n) O(n)
如果从左向右遍历,每次需要将后面的所有字符向右移动,时间复杂度为 O ( n 2 ) O(n^2) O(n2)

class Solution {
public:
    string replaceSpace(string s) {
        int s_len = s.length();
        int space_cnt = 0;
        for (int i = 0; i < s_len; ++i) { // 统计空格的数量
            if (s[i] == ' ') space_cnt++;
        }
        int new_len = s_len + space_cnt * 2;
        s.resize(new_len); // 扩展字符串空间
        for (int i = s_len - 1, j = new_len - 1; i < j; i--, j--) {
            if (s[i] == ' ') {
                s[j--] = '0';
                s[j--] = '2';
                s[j] = '%';
            } else s[j] = s[i];
        }
        return s;
    }
};

4. 反转字符串中的单词

151. 反转字符串中的单词
思路:

如果使用单词数组的话将变得很简单,只需要首尾交换单词即可,但是空间复杂度为 O ( n ) O(n) O(n)
如果要空间复杂度为 O ( 1 ) O(1) O(1),就不能另开一个数组

  1. 将整个字符串反转
  2. 然后去除开头,中间,结尾多余的空格
  3. 将每个单词反转回来
class Solution {
public:
    void my_remove_extra_space(string &s) { // 去除字符串中多余的空格
        int s_len = s.length();
        int slow_index = 0;
        for (int fast_index = 0;  fast_index < s_len; ++fast_index) {
            if (s[fast_index] != ' ') {
                if (slow_index != 0) s[slow_index++] = ' '; // 单词之间添加空格
                while (s[fast_index] != ' ' && fast_index < s_len) s[slow_index++] = s[fast_index++];
            }
        }
        s.resize(slow_index);
    }

    void my_reverse(string &s, int left, int right) { // 将字符串left到right的部分反转
        char temp;
        while (left < right) {
            temp = s[left];
            s[left++] = s[right];
            s[right--] = temp;
        }
    }

    string reverseWords(string s) {
        my_remove_extra_space(s);
        int s_len = s.length();
        my_reverse(s, 0, s_len - 1);

        int left = 0, right;
        for (int i = 0; i <= s_len; ++i) {
            if (i == s_len || s[i] == ' ') {
                right = i - 1;
                my_reverse(s, left, right); // 把每个单词反转回来
                left = i + 1;
            }
        }
        return s;
    }
};

5. 左旋转字符串

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

如果整体移动的话空间复杂度为 O ( n 2 ) O(n^2) O(n2)
这里用一个 O ( n ) O(n) O(n)的方法,原地左旋字符串

  1. 将[0, k)的字符串反转
  2. 将[k, s_len)的字符串反转
  3. 将整个字符串反转回来

太妙了!佩服佩服

class Solution {
public:
    void my_reverse(string &s, int left, int right) {
        while (left < right) {
            swap(s[left++], s[right--]);
        }
    }

    string reverseLeftWords(string s, int n) {
        int s_len = s.length();
        my_reverse(s, 0, n - 1);
        my_reverse(s, n, s_len - 1);
        my_reverse(s, 0, s_len - 1);
        return s;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值