📘 題目敘述
你會得到一個字串 s,其中只包含 小寫英文字母 與 特殊字元。
你的任務是依序做以下兩件事:
- 把所有小寫字母反轉,並把它們放回原本「字母所佔的位置」上。
- 把所有特殊字元反轉,並把它們放回原本「特殊字元所佔的位置」上。
完成上述兩次反轉後,回傳最後得到的字串。
條件限制
1 <= s.length <= 100s只會包含小寫英文字母,以及"!@#$%^&*()"這些特殊字元。
🧠 解題思路
這題其實是在做「同類型字元各自反轉,但位置類型不變」。
我的做法是:
- 先掃一次字串,把
- 所有 字母的位置 index 收集到
low - 所有 特殊字元的位置 index 收集到
spe
- 所有 字母的位置 index 收集到
- 先複製一份字串
ns = s當作答案容器(保留原長度與所有位置) - 接著分兩次把字元「倒著塞回去」:
- 對
low:用ns[low[nl-1-j]] = s[low[j]]代表「把第 j 個字母,放到倒數第 j 個字母的位置」 - 對
spe:用ns[spe[np-1-k]] = s[spe[k]]代表「把第 k 個特殊字元,放到倒數第 k 個特殊字元的位置」
- 對
這樣就能同時達成:
- 字母只會回到字母的位置
- 特殊字元只會回到特殊字元的位置
- 兩群各自完成反轉
所有變數
n:字串s的長度low:存放「小寫字母」在s裡的 indexspe:存放「特殊字元」在s裡的 indexns:答案字串(先複製s,再把反轉後的字元塞回去)nl:low.size(),字母的數量np:spe.size(),特殊字元的數量
🪜 主要流程步驟
1. 掃描字串,把位置分成兩類
- 走訪
s的每個位置i - 如果
s[i]是'a' ~ 'z':- 把
i加進low
- 把
- 否則:
- 把
i加進spe
- 把
2. 初始化答案字串
- 用
string ns = s;先把所有字元原樣放著,等等只要「覆寫」要反轉的那些位置即可
3. 只反轉字母(回填到字母位置)
nl = low.size()- 對
j = 0 .. nl-1:ns[low[nl - 1 - j]] = s[low[j]]
4. 只反轉特殊字元(回填到特殊字元位置)
np = spe.size()- 對
k = 0 .. np-1:ns[spe[np - 1 - k]] = s[spe[k]]
5. 回傳結果
- 回傳
ns
💻 程式碼實作
class Solution {
public:
string reverseByType(string s) {
int n = s.size();
vector<int> low;
vector<int> spe;
string ns = s;
for (int i = 0; i < n; i++) {
if (s[i] >= 'a' && s[i] <= 'z') {
low.push_back(i);
} else {
spe.push_back(i);
}
}
int nl = low.size();
for (int j = 0; j < nl; j++) {
ns[low[nl - 1 - j]] = s[low[j]];
}
int np = spe.size();
for (int k = 0; k < np; k++) {
ns[spe[np - 1 - k]] = s[spe[k]];
}
return ns;
}
};
🔗 題目連結
https://leetcode.com/problems/reverse-letters-then-special-characters-in-a-string/