Day8 字符串 LeetCode 344 541 151 剑指05 58II

65 阅读2分钟

344. 反转字符串

思路

  • 双指针,可以用库函数,当库函数不是关键部分且是代码一部分时可以用

题解

  • swap还有位运算实现
// swap
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];
class Solution {
public:
    void reverseString(vector<char>& s) {
        for (int i = 0, j = s.size() - 1; i < s.size() / 2; i++, j--) {
            swap(s[i], s[j]);
        }
    }
};

541. 反转字符串 II

思路

  • 同样双指针法,注意使用库函数,设置步长即可

题解

class Solution {
public:
    void reverse(string &s, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--){
            swap(s[i], s[j]);
        }
    }
    string reverseStr(string s, int k) {
        for (int i = 0; i < s.size(); i += 2 * k) {
            if ((i + k) <= s.size()) {
                reverse(s, i, i + k -1);
                continue;
            }
            reverse(s, i, s.size() - 1);
        }

        return s;

    }
};

剑指 Offer 05. 替换空格

心得

  • 新数组替换即可,可考虑最优的O(1)空间复杂度解法

题解

  • 双指针可以原地替换,很多数组填充类可以扩容从后面开始,很好用,而从前往后O(N^2)
class Solution {
public:
    string replaceSpace(string s) {
        int count = 0;
        int soldSize = s.size();
        int snewSize = 0;
        for (int i = 0; i < soldSize; i++) {
            if (s[i] == ' ') {
                count++;
            }
        }
        snewSize = soldSize + count;
        s.resize(soldSize + 2 * count);
        for (int i = soldSize - 1, j = snewSize - 1; i < j; i--, j--) {
            if (s[i] != ' ') {
                s[j] = s[i];
            } else {
                s[j] = '0';
                s[j-1] = '2';
                s[j-2] = '%';
                j -= 2;
            }a
        }
        return s;

    }
};

151. 反转字符串中的单词

心得

  • 考虑利用入栈,出栈时,判断单词翻转,其实再想一步就能想出空间复杂度O(1)的解法

题解

  • 双指针移除元素空格,然后翻转,变逆序,再对单词进行翻转即可
  • 单词级别翻转,如果直接双指针,收尾单词长度不一致,必然会覆盖,故考虑分步走,先整体翻转,再局部翻转,然后添加局部单词判断即可,涉及到空格提前移除即可
  • 时间复杂度O(N),空间复杂度O(1)
class Solution {
public:
    void reverse(string &s, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--) {
            swap(s[i], s[j]);
        }
    }

// 双指针法移除空格,类似数组移除元素
    void removeExtraSpaces(string &s) {
        int slow = 0;
        for (int i = 0; i < s.size(); i++) {
            if (s[i] != ' ') {
                if (slow != 0) s[slow++] = ' '; // 非首元素需要添加空格
                while (i < s.size() && s[i] != ' ') {
                    s[slow++] = s[i++];
                }
            }            

        }
        s.resize(slow); // 此时重新调整大小,slow为索引,++后为元素大小
    }

    string reverseWords(string s) {
        removeExtraSpaces(s);
        reverse(s, 0, s.size() - 1);
        int start = 0;
        for (int i = 0; i <= s.size(); i++) { // 取等号考虑末尾特殊处理
            if (i == s.size() || s[i] == ' ') { // 考虑末尾元素
                reverse(s, start, i-1); // 左闭右闭移除元素
                start = i + 1;
            }
        }
        return s;
    }
};

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

心得

  • 原来想的是按照窗口翻转,思路类似,但是没想到题解这么妙

题解

  • 类似单词翻转,局部集合整体翻转即可,库函数reverse左闭右开,end默认为开
  • 时空复杂度N 1
class Solution {
public:
    string reverseLeftWords(string s, int n) {
        reverse(s.begin(), s.begin() + n);
        reverse(s.begin() + n, s.end());
        reverse(s.begin(), s.end());
        return s;

    }
};