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

目录

344.反转字符串

思路

代码实现

总结

541. 反转字符串II

思路

代码实现

总结

剑指Offer 05.替换空格

思路

代码实现

总结

151.翻转字符串里的单词

思路

代码实现

总结

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

思路

代码实现

总结


344.反转字符串

题目链接:344. 反转字符串

思路

利用双指针,分别从头、尾开始,相互交换位置。

代码实现

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

541. 反转字符串II

题目链接:541. 反转字符串 II

思路

先将前k个字符反转,然后跳过k个字符,重复上述操作;

代码实现

class Solution {
public:
    string reverseStr(string s, int k) {
        int size = s.size();
        int curr = 0;
        while(curr < size){
            if(k == 1)  break;
            // 反转前k个字符
            int right;
            if(curr + k - 1 < size)  right = curr + k - 1;
            else    right = size - 1;
            for(int left = curr; left < right; ++left, --right){
                swap(s[left], s[right]);
            }
            // 跳过k个字符
            curr += 2 * k;
        }
        return s;
    }
};

小结

这里反转字符可以使用库函数reverse,要学会使用库函数。

LCR 122. 路径加密

呃呃本来是剑指Offer的,但是力扣题目下架了,换题!题目简单了好多,原题是:剑指Offer 05.替换空格

题目链接:LCR 122. 路径加密

代码实现

class Solution {
public:
    string pathEncryption(string path) {
        for(int i = 0; i < path.size(); ++i){
            if(path[i] == '.')  path[i] = ' ';
        }
        return path;
    }
};

剑指Offer 05.替换空格

这一题没做,但是看到了解析,感觉又是很巧妙,先判断有多少个空格,预留出足够的位置,再利用双指针从后往前填充字符串。

151.翻转字符串里的单词

题目链接:151. 反转字符串中的单词

思路与代码实现

这题我的思路是,先把每个单词的首字母位置记录下来,然后再从后向前将各个单词录入新字符串中。不过这种算法的内存使用有点高

class Solution {
public:
    string reverseWords(string s) {
        int size = s.size();
        // 记录各单词首字母的位置
        stack init;
        init.push(0);
        for(int i = 1; i < size; ++i){
            if(s[i - 1] == ' ' && s[i] != ' ') init.push(i);
        }
        // 从后往前录入新字符串
        string result;
        while(!init.empty()){
            for(int i = init.top(); s[i] != ' ' && i < size; ++i){
                result = result + s[i];
            }
            init.pop();
            result += ' ';
        }
        while(result[result.size()-1] == ' ')
            result.erase(result.end() - 1);
        return result;
    }
};

不要使用辅助空间,空间复杂度要求为O(1)。

要求空间以后,就有点难了,解析上的思路却很巧,先将整个字符串反转,再将哥哥单词反转,这样就成了今天前两道题的结合;值得注意的是,去除多余空格时,考虑到时间复杂度的问题,可采用双指针的方法,而不是erase。

class Solution {
public:
    string reverseWords(string s) {
        int size = s.size();
        // 利用双指针除去多余空格
        int slow = 0;
        for(int fast = 0; fast < size; ++fast){
            if(s[fast] != ' '){
                if(slow > 0)    s[slow++] = ' ';
                while(s[fast] != ' ' && fast < size)    s[slow++] = s[fast++];
            }
        }
        s.resize(slow);
        size = slow;

        // 整体反转
        reverse(s.begin(), s.end());
        // 各个单词反转
        slow = 0;
        for(int fast = 0; fast <= size; ++fast){
            if(fast == size || s[fast] == ' '){
                reverse(s.begin() + slow, s.begin() + fast);
                slow = fast + 1;
            }
        }

        return s;
    }
};

小结

实现反转,无从下手,可以试试看是不是局部反转和整体反转的结合而成;去除多余空格,可以和27.移除元素相联系起来。

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

题目链接:LCR 182. 动态口令(力扣题目下架了,这题题意相同)

思路

为了让本题更有意义,提升一下本题难度:不能申请额外空间,只能在本串上操作

根据上一题的思路,这一题也试试局部反转加整体反转:

        首先将所得结果整体反转,得到的是前target个字符局部反转,其后字符局部反转;所以反推,原字符串前target个字符反转,后面也反转,再整体反转就能得到最终结果。

代码实现

class Solution {
public:
    string dynamicPassword(string password, int target) {
        // 先反转前target个字符
        reverse(password.begin(), password.begin() + target);
        // 再反转其后字符
        reverse(password.begin() + target, password.end());
        // 再整体反转
        reverse(password.begin(), password.end());
        return password;
    }
};

你可能感兴趣的:(算法,leetcode,c++)