Easy
题目描述
给定一个由小写英文字母和特殊字符组成的字符串 s。
你需要按顺序执行以下操作:
- 反转小写字母,并将它们放回原本字母占据的位置。
- 反转特殊字符,并将它们放回原本特殊字符占据的位置。
返回执行反转操作后的结果字符串。
示例 1:
输入:s = ")ebc#da@f("
输出:"(fad@cb#e)"
解释:
字符串中的字母为 ['e', 'b', 'c', 'd', 'a', 'f']:
- 反转后为 ['f', 'a', 'd', 'c', 'b', 'e']
- s 变为 ")fad#cb@e("
字符串中的特殊字符为 [')', '#', '@', '(']:
- 反转后为 ['(', '@', '#', ')']
- s 变为 "(fad@cb#e)"
示例 2:
输入:s = "z"
输出:"z"
解释:
字符串只包含一个字母,反转不改变字符串。没有特殊字符。
示例 3:
输入:s = "!@#$%^&*()"
输出:")(*&^%$#@!"
解释:
字符串不包含字母。字符串包含所有特殊字符,所以反转特殊字符就是反转整个字符串。
提示:
1 <= s.length <= 100s只由小写英文字母和特殊字符"!@#$%^&*()"组成。
解题思路
这道题需要分别对字母和特殊字符进行反转操作,可以使用双指针方法来解决。
核心思路:
- 首先将字符串转换为字符数组,便于修改
- 使用双指针分别处理字母和特殊字符的反转:
- 对于字母反转:左指针从头开始,右指针从尾开始,只处理字母位置,跳过特殊字符
- 对于特殊字符反转:同样使用双指针,只处理特殊字符位置,跳过字母
算法步骤:
- 第一轮双指针遍历:反转所有字母
- 左指针向右移动直到遇到字母
- 右指针向左移动直到遇到字母
- 交换两个位置的字母,继续移动指针
- 第二轮双指针遍历:反转所有特殊字符
- 左指针向右移动直到遇到特殊字符
- 右指针向左移动直到遇到特殊字符
- 交换两个位置的特殊字符,继续移动指针
这种方法的优势是只需要遍历字符串两次,时间效率高,且逻辑清晰易懂。
推荐解法: 双指针方法,因为它直观、高效,符合题目提示。
代码实现
class Solution {
public:
string reverseByType(string s) {
vector<char> chars(s.begin(), s.end());
int n = chars.size();
// 反转字母
int left = 0, right = n - 1;
while (left < right) {
while (left < right && !isalpha(chars[left])) left++;
while (left < right && !isalpha(chars[right])) right--;
if (left < right) {
swap(chars[left], chars[right]);
left++;
right--;
}
}
// 反转特殊字符
left = 0;
right = n - 1;
while (left < right) {
while (left < right && isalpha(chars[left])) left++;
while (left < right && isalpha(chars[right])) right--;
if (left < right) {
swap(chars[left], chars[right]);
left++;
right--;
}
}
return string(chars.begin(), chars.end());
}
};
class Solution:
def reverseByType(self, s: str) -> str:
chars = list(s)
n = len(chars)
# 反转字母
left, right = 0, n - 1
while left < right:
while left < right and not chars[left].isalpha():
left += 1
while left < right and not chars[right].isalpha():
right -= 1
if left < right:
chars[left], chars[right] = chars[right], chars[left]
left += 1
right -= 1
# 反转特殊字符
left, right = 0, n - 1
while left < right:
while left < right and chars[left].isalpha():
left += 1
while left < right and chars[right].isalpha():
right -= 1
if left < right:
chars[left], chars[right] = chars[right], chars[left]
left += 1
right -= 1
return ''.join(chars)
public class Solution {
public string ReverseByType(string s) {
char[] chars = s.ToCharArray();
int n = chars.Length;
// 反转字母
int left = 0, right = n - 1;
while (left < right) {
while (left < right && !char.IsLetter(chars[left])) left++;
while (left < right && !char.IsLetter(chars[right])) right--;
if (left < right) {
(chars[left], chars[right]) = (chars[right], chars[left]);
left++;
right--;
}
}
// 反转特殊字符
left = 0;
right = n - 1;
while (left < right) {
while (left < right && char.IsLetter(chars[left])) left++;
while (left < right && char.IsLetter(chars[right])) right--;
if (left < right) {
(chars[left], chars[right]) = (chars[right], chars[left]);
left++;
right--;
}
}
return new string(chars);
}
}
var reverseByType = function(s) {
const chars = s.split('');
const n = chars.length;
// 反转字母
let left = 0, right = n - 1;
while (left < right) {
while (left < right && !/[a-z]/.test(chars[left])) left++;
while (left < right && !/[a-z]/.test(chars[right])) right--;
if (left < right) {
[chars[left], chars[right]] = [chars[right], chars[left]];
left++;
right--;
}
}
// 反转特殊字符
left = 0;
right = n - 1;
while (left < right) {
while (left < right && /[a-z]/.test(chars[left])) left++;
while (left < right && /[a-z]/.test(chars[right])) right--;
if (left < right) {
[chars[left], chars[right]] = [chars[right], chars[left]];
left++;
right--;
}
}
return chars.join('');
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 需要遍历字符串两次,每次都是 O(n) |
| 空间复杂度 | O(n) | 需要额外的字符数组来存储结果 |
相关题目
- . Reverse Only Letters (Easy)