题目

给你一个字符串 s ,根据下述规则反转字符串:

  • 所有非英文字母保留在原有位置。
  • 所有英文字母(小写或大写)位置反转。

返回反转后的 s 。

示例:

输入:s = "ab-cd"

输出:"dc-ba"


解答

普通解法

依次遍历字符串 s ,通过栈保存每一个字母元素,然后再次遍历,将是字母元素的位置替换为出栈元素。

class Solution {
public:
    string reverseOnlyLetters(string s) {
        int n = s.size();
        stack<char> st;

        for (int i = 0; i < n; ++i) {
            if ((s[i] >= 'a' && s[i] <= 'z') ||
                (s[i] >= 'A' && s[i] <= 'Z')) {
                st.push(s[i]);
            }
        }

        for (int i = 0; i < n; ++i) {
            if ((s[i] >= 'a' && s[i] <= 'z') ||
                (s[i] >= 'A' && s[i] <= 'Z')) {
                auto get = st.top();
                st.pop();
                s[i] = get;
            }
        }

        return s;
    }
};

双指针

通过左右指针,依次从最左侧和最右侧遍历字符串 s,如果l和r指向的均为字母,则互换内容,并继续遍历,知道l和r重合。

class Solution {
public:
    string reverseOnlyLetters(string s) {
        int n = s.size();

        // 双指针
        int l = 0;
        int r = n - 1;

        while (l < r) {
            while ((l < r) && !((s[l] >= 'a' && s[l] <= 'z') || (s[l] >= 'A' && s[l] <= 'Z'))) {
                l++;
            }
            while ((l < r) && !((s[r] >= 'a' && s[r] <= 'z') || (s[r] >= 'A' && s[r] <= 'Z'))) {
                r--;
            }

            if (l < r) {
                auto tmp = s[l];
                s[l++] = s[r];
                s[r] = tmp;
                r--;
            }
        }

        return s;
    }
};