算法Day08 | 344.反转字符串,541. 反转字符串II,替换空格, 151.翻转字符串里的单词,剑指Offer58-II.左旋转字符串

文章介绍了多个关于字符串反转的编程问题解决方案,包括344.反转字符串、541.反转字符串II、剑指Offer05.替换空格、151.翻转字符串里的单词以及剑指Offer58-II.左旋转字符串。解题策略涉及双指针、位运算和字符串拼接及反转等技巧。

344.反转字符串

题目链接:344.反转字符串
一眼丁真 指针

class Solution {
public:
    void reverseString(vector<char>& s) {
        int left = 0, right = s.size() - 1;
        while (left < right) {//当s为奇数时,直接跳过。当s为偶数时,交换后自动满足
            s[left++] ^= s[right--] ^= s[left] ^= s[right];//交换。此方法仅限于整数,char在底层也算整数         
        }
    }
};

因为^=操作符是right to left,所以最后执行的leftright上有自增自减

class Solution {
    template <class T>
    void fun(T& a, T& b) {
        T tmp;
        tmp = a;
        a = b;
        b = tmp;
    }
public:
    void reverseString(vector<char>& s) {
        int left = 0, right = s.size() - 1;
        while (left < right) {
            fun(s[left++], s[right--]);
        }
    }
};

仿照算法std::reverse()函数写的

class Solution {
public:
    //仿照算法reverse函数写的
    void reverseString(vector<char>& s) {
        int fisrt = 0, last = s.size();
        while ((fisrt != last) && (fisrt != --last)) {
            swap(s[fisrt++], s[last]);
        }
    }
};

541. 反转字符串II

题目链接:541. 反转字符串II
仔细读题,虽然leetcode表述也有歧义。

class Solution {
public:
    string reverseStr(string s, int k) {
        for (int idx = 0; idx < s.size(); idx += 2 * k/*每2k个判断一次*/) {
            (idx + k < s.size())//剩余字符是否有k个
                //reverse函数区间为左闭右开
                ? reverse(s.begin() + idx, s.begin() + idx + k)//有,结尾为 + k
                : reverse(s.begin() + idx, s.end());//没有就直接到end
        }
        return s;
    }
};

reverse函数参数是迭代器形式。
revese(s.begin(), s.end()),由end()定义为容器最后一位的下一位可知,reverse为左闭右开。
可以通过修改for循环计数语句,来修改遍历形式。i += 2 * k,视为将 2 * k 为一个单元。


替换空格

题目链接:已被Leetcode删除
用双指针。只需要在原来的字符串(内存上)修改。从后往前遍历时间复杂度就为 O ( n ) O(n) O(n),从前往后为 O ( n 2 ) O(n^2) O(n2),因为填充一次后,还要整体移动后续字符。
其实很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。

class Solution {
public:
    string replaceSpace(string s) {
        int cnt = 0;//计算空格次数
        for (auto& i : s) {
            if (i == ' ') {
                cnt++;
            }
        }
        s.resize(s.size() + cnt * 2);//扩容
        //slow指向原来数组长度结尾,fast指向新数组的结尾。
        int slow = s.size() - 1 - 2 * cnt, fast = s.size() - 1;//从后往遍历
        while (slow < fast) {//当两指针相遇,表示没有空格了,直接跳过就行。
            if (s[slow] != ' ') {
                s[fast--] = s[slow--];//原来赋给新的,都往前移一位
            } else {
                slow--;
                s[fast--] = '0';
                s[fast--] = '2';
                s[fast--] = '%';
            }
        }
        return s;
    }
};

151.翻转字符串里的单词

题目链接: 151.翻转字符串里的单词

  • step 1. 去除空格:" wo he " -> "wo he"
  • step 2. 反转整体 :"wo he"->"eh ow"
  • step 3. 反转单词 :"eh ow"->"he wo"

整体代码如下:

class Solution {
    void removeSpace(string& par) {
        int newIdx = 0;
        for (int oldIdx = 0; oldIdx < par.size(); ++oldIdx) {
            if (par[oldIdx] != ' ') {//跳过空格
                if (newIdx != 0) {//非第一个单词
                    par[newIdx++] = ' ';//每个单词前都加空格
                }
                while (oldIdx < par.size()/*因为在下一行代码中,oldIdx++,所以要判断一下*/ && par[oldIdx] != ' ') {
                    par[newIdx++] = par[oldIdx++];
                }
            }
        }
        par.resize(newIdx);//因为循环最后一步为newIdx++,所以不是resize(newIdx + 1)
    }
    void reverseString(string& par, int left, int right) {
        while (left < right) {
            par[left++] ^= par[right--] ^= par[left] ^= par[right];
        }
    }
public:
    string reverseWords(string s) {
        removeSpace(s);
        reverseString(s, 0, s.size() - 1);
        int start = 0;//用来修改每个单词的翻转
        for (int idx = 0; idx <=/*等于是为了让最后一个单词也满足翻转的区间*/ s.size(); ++idx) {
            if (s[idx] == ' ' || idx == s.size()/*最后一个单词*/) {
                reverseString(s, start, idx - 1);
                start = idx + 1;//更新起点
            }
        }
        return s;
    }
};

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

题目链接:剑指Offer58-II.左旋转字符串
一眼字符串拼接。结果说反转。太离谱了。

class Solution {
public:
    string reverseLeftWords(string s, int n) {
        //字符串拼接
/*        string tmp;
        for (int i = n; i < s.size(); ++i) {
            tmp += s[i];
        }
        for (int i = 0; i < n; i++) {
            tmp += s[i];
        }
        return tmp;*/
//三个反转
        reverse(s.begin(), s.begin() + n);//反转前n个
        reverse(s.begin(), s.end());//全反转
        reverse(s.begin(), s.end() - n);//反转前end - n个
        return s;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值