[解题报告] 《算法零基础100讲》(第25讲) 字符串算法(五) - 字符串反转

目录

  • 前言
  • 一、反转字符串
  • 二、反转单词前缀
  • 三、反转字符串中的元音字母
  • 四、翻转单词顺序
  • 五、翻转字符串里的单词
  • 六、反转字符串中的单词 III
  • 六、反转字符串 II
  • 七、仅仅反转字母
  • 八、整数反转


前言

跟着英雄哥打卡第二十五天
[专题跳转->《算法零基础100讲》]
[万人千题社区跳转]


一、反转字符串

跳转力扣:344. 反转字符串

难度:★☆☆☆☆
说明:基础的字符串翻转问题,双指针实现头尾交换,每交换一次向中间靠拢,直至两个指针相遇
代码如下(示例):

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

二、反转单词前缀

跳转力扣:2000. 反转单词前缀

难度:★☆☆☆☆
说明:使用字符串内置函数find()查找是否存在查找的字母,若未找到直接返回原字符串,若找到可用reverse函数实现从下标为0到下标为f之间的字符串翻转
代码如下(示例):

class Solution {
public:
    string reversePrefix(string word, char ch) {
        int f = word.find(ch);
        if (f == -1) return word;
        reverse(word.begin(), word.begin() + f + 1);
        return word;
    }
};

三、反转字符串中的元音字母

跳转力扣:345. 反转字符串中的元音字母

难度:★☆☆☆☆
说明:使用yy字符串存储元音字母以便在判断是否为元音字母的check()函数中遍历时使用,同样使用头尾双指针查找离两端最近的元音字母,并实现交换,直至两个指针相遇
代码如下(示例):

class Solution {
public:
    string yy = "aeiouAEIOU";
    bool check(char c) {
        for (auto &y: yy) {
            if (c == y) return true;
        }
        return false;
    }
    string reverseVowels(string s) {
        int l = 0, r = s.size() - 1;
        while (l < r) {
            while (l < r && !check(s[l])) l ++;
            while (l < r && !check(s[r])) r --;
            if (l < r) {
                swap(s[l], s[r]);
                l ++, r --;                
            }
        }
        return s;
    }
};

四、翻转单词顺序

跳转力扣:剑指 Offer 58 - I. 翻转单词顺序

难度:★★☆☆☆
说明:先对空字符串"“做一个特判,后对头尾的空格进行删除,删除结束后若尾指针跑到头指针前面去了,说明该字符串为全空格字符串,直接返回空字符串”",否则截取从i到j之间的字符串作为我们将要研究的字符串,为方便判断可以在字符串头部加一个空格方便后续判断;
j指针记录当前从后往前遍历到的位置,i表示从后往前遍历到的单词的第一个字母的位置,若j遇到空格则表示该单词记录结束,用substr()函数截取子串,并加入到答案中;
特别注意:遍历时需要做跳过连续的空格的操作,并注意字符串越界致命问题

代码如下(示例):

class Solution {
public:
    string reverseWords(string s) {
        int i = 0, j = s.size() - 1;
        if (s == "") return "";
        while (i <= j && s[i] == ' ') i ++;
        while (j >= 0 && s[j] == ' ') j --;
        if (i > j) return "";
        s = s.substr(i, j - i + 1);
        s = " " + s;
        string res, ans = "";
        for (int j = s.size() - 1, i = s.size() - 1; j >= 0; j --) {
            if (s[j] == ' '){
                ans += s.substr(j + 1, i - j);
                if (j != 0)
                    ans += ' ';
                if (j > 0)
                    while (s[j-1] == ' ') j --;
                i = j - 1;
            }
        }
        return ans;
    }
};

五、翻转字符串里的单词

跳转力扣:151. 翻转字符串里的单词

难度:★★☆☆☆
说明:与上题相同

六、反转字符串中的单词 III

跳转力扣:557. 反转字符串中的单词 III

难度:★★☆☆☆
说明:手写myreverse函数实现字符串翻转,res维护单词,ans维护答案句子,同样在尾部加入空格字符为后续方便判断,遍历字符串若遇到空格,则将存储的字符串翻转后存入句子中,注意存入后续讲存储的单词清空后再进行下一次循环操作,每个单词后加入空格,除最后一个外,因此需要做一个特判
代码如下(示例):

class Solution {
public:
    string myreverse(string s) {
        for (int l = 0, r = s.size() - 1; l < r; l ++, r --) {
            swap(s[l], s[r]);
        }
        return s;
    }
    string reverseWords(string s) {
        s += ' ';
        string res, ans;
        for (int i = 0; i < s.size(); i ++) {
            if (s[i] != ' ')
                res += s[i];
            else {
                ans += myreverse(res);
                if (i != s.size() - 1)
                    ans += ' ';
                res = "";
            }
        }
        return ans;
    }
};

六、反转字符串 II

跳转力扣:541. 反转字符串 II

难度:★★☆☆☆
说明:手写myreverse函数实现字符串翻转,res维护单词,ans维护答案句子,此题最难处理的是越界问题,首先每一段2*k的区间判断需要翻转的前半部分是否超出字符串,若已超出则对前半部分剩余的进行翻转即可(不需要再将后半部分插入,会越界),若未超出需要将前半部分的字符串翻转加入ans中,并将后半部分的加入ans中
代码如下(示例):

class Solution {
public:
    string myreverse(string s) {
        for (int l = 0, r = s.size() - 1; l < r; l ++, r --) {
            swap(s[l], s[r]);
        }
        return s;
    }
    string reverseStr(string s, int k) {
        string res, ans;
        for (int i = 0; i < s.size(); i += 2*k) {
            
            if (i + k > s.size() - 1){
                ans += myreverse(s.substr(i, k));
            }
            else {
                ans += myreverse(s.substr(i, k));
                ans += s.substr(i + k, k);
            }
        }
        return ans;
    }
};

七、仅仅反转字母

跳转力扣:917. 仅仅反转字母

难度:★★☆☆☆
说明:头尾双指针,找到距离头尾两端最近的字母,用swap()函数交换,交换后两个指针向中间靠拢,循环操作直至两个指针相遇
代码如下(示例):

class Solution {
public:
    string reverseOnlyLetters(string s) {
        int l = 0, r = s.size() - 1;
        while (l < r) {
            while (l < r && !isalpha(s[l])) l ++;
            while (l < r && !isalpha(s[r])) r --;
            if (l < r) swap(s[l], s[r]);
            l ++, r --;
        }
        return s;
    }
};

八、整数反转

跳转力扣:7. 整数反转

难度:★★☆☆☆
说明:由于有“如果反转后整数超过 32 位的有符号整数的范围 [−2^31, 2^31 − 1] ,就返回 0”的限制,需要每次左移的时候对目前数字判断是否超过整数的范围。
代码如下(示例):

class Solution {
public:
    int reverse(int x) {
        int rev = 0;
        while(x != 0){
            int pop = x % 10;
            x /= 10;
            if(rev > INT_MAX/10 || (rev == INT_MAX/10 && pop > 7)) return 0;
            if(rev < INT_MIN/10 || (rev == INT_MIN/10 && pop < -8)) return 0;
            rev = rev*10 + pop;
        }
        return rev;
    }
};

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