[代码随想录算法训练营]刷题笔记 Day 8

344.反转字符串

双指针代码应用

class Solution {
public:
    void reverseString(vector<char>& s) {
        int size = s.size();

        for(int left = 0, right = size - 1; right > left; left++, right--){
            swap(s[left],s[right]);
        }
    }
};

541. 反转字符串II

很快就想出思路了,但有小细节没有做好。

class Solution {
public:
    string reverseStr(string s, int k) {

        for(int index = 0 ; index < s.size(); index += (k * 2)){
            int left = index;
            int right = (index + k ) < s.size() ? (index + k - 1) : (s.size() - 1);

            while(left < right){
                swap(s[left++], s[right--]);
            }
        }

        return s;
    }
};

剑指Offer 05.替换空格

先计算出填充后字符串得大小,再由后面往前面遍历填入。

class Solution {
public:
    string replaceSpace(string s) {
        int oldSize = s.size();
        int count = 0;

        // 计算有多少空格
        for(char c : s){
            if(c == ' ') count++;
        }

        // 重新给予s的大小
        s.resize(oldSize + 2 * count);
        int newSize = s.size();

        // 从后面往前替换,如果从前面开始跳换需要两个for回圈来替换字符
        for(int i = oldSize - 1, j = newSize - 1; i >= 0; i--, j-- ){
            if(s[i] != ' '){
                s[j] = s[i];
            }
            else{
                s[j] = '0';
                s[j - 1] = '2';
                s[j - 2] = '%';
                j = j - 2;
            }
        }
        
        return s;
    }
};

151.翻转字符串里的单词

暴力解

将单词提取出来放到stack里面,在一个一个加上。

class Solution {
public:
    string reverseWords(string s) {
        stack<string> words;
        string result; 
        for(int i = 0, j = 0; i < s.size(); ){
            if(s[i] != ' '){
                string tmp;
                while(s[j] != ' ' && s[j] != '\0'){
                    tmp += s[j++];
                    cout << tmp << endl;
                }
                words.push(tmp);
                i = j;
            }
            else{
                i++;
                j++;
            }
        }
        result += words.top();
        words.pop();
        
        while(!words.empty()){
            result += ' ';
            result += words.top();
            words.pop();
        }
        return result;
    }
};
空间复杂度O(1)解法

解题思路如下:

  • 移除多余空格
  • 将整个字符串反转
  • 将每个单词反转

举个例子,源字符串为:"the sky is blue "

  • 移除多余空格 : “the sky is blue”
  • 字符串反转:“eulb si yks eht”
  • 单词反转:“blue is sky the”
class Solution {
public:
    void removeExtraSpaces(string& s){
        int slow = 0;
        // 利用快指针来遍历字符串,慢指针来修正字符串
        // 快指针跳过所有空格,慢指针手动加上空格,保证字符串的空格都是有效正确的
        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++];
                }
            }
        }
        // slow的大小即为去除多余空格后的大小。
        s.resize(slow);

        cout << s << endl;
    }   

    void reverseString(string& s, int start, int end){
        // 利用双指针将整个字符串颠倒
        int left = start;
        int right = end;

        while(right > left){
            swap(s[left++], s[right--]);
        }
        
        cout << s << endl;
    }
    
    string reverseWords(string s) {
        // 去除多余空格
        removeExtraSpaces(s);
        // 反转整个字符串
        reverseString(s, 0, s.size() - 1);

        // 利用快慢指针翻转单字
        int slow = 0;

        for(int fast = 0; fast < s.size(); fast++){
            // 找寻单字的边界,如果是空格或者是整个字符串最后一位说明到了单字的边界
            if(fast == s.size() - 1 || s[fast] == ' '){
                int left = slow;
                int right = s[fast] == ' ' ? fast - 1 : fast;
                reverseString(s, left, right);
                slow = fast + 1;
            }
        }

        return s;
    }
};

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

可以通过局部反转+整体反转 达到左旋转的目的。

具体步骤为:

  • 反转区间为前n的子串
  • 反转区间为n到末尾的子串
  • 反转整个字符串
class Solution {
public:
    void reverseString(string& s, int start, int end){
        if(start < 0 || end < 0 || start > end || start >= s.size() || end >= s.size()){
            cout << "Indexs exceed boundaries" << endl;
            return;
        }
        while(start < end){
            swap(s[start++],s[end--]);
        }
    }
    string reverseLeftWords(string s, int n) {
        // 首先先以n为界限反转 (0->n-1) (n->end)
        // 在整个字符串翻转即可
        reverseString(s, 0, n-1);
        reverseString(s, n, s.size() - 1);
        reverseString(s, 0, s.size() - 1);

        return s;
    }
};

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