「这是我参与2022首次更文挑战的第36天,活动详情查看:2022首次更文挑战」。
题目
给你一个字符串 s ,根据下述规则反转字符串:
所有非英文字母保留在原有位置。
所有英文字母(小写或大写)位置反转。
返回反转后的 s 。
示例 1:
输入:s = "ab-cd"
输出:"dc-ba"
示例 2:
输入:s = "a-bC-dEf-ghIj"
输出:"j-Ih-gfE-dCba"
示例 3:
输入:"Test1ng-Leet=code-Q!"
输出:"Qedo1ct-eeLg=ntse-T!"
思路
直观
一拿到这个题目,想到的直观思路是这样的:
- 遍历原始字符串,获取出英文字母,加入新的中间字符串snew
- 反转中间字符串snew,形成sre
- 遍历原始字符串,如果该位置不是英文字母,保持不变;如果是英文字母,从sre中获取当前指针指向的字符,指针从0开始,获取一次就向后走一步
我们用示例1的输入来走一遍:
- 遍历s,取出英文字母,形成snew = "abcd"
- 反转abcd,形成sre = "dcba"
- 遍历原始字符串:
- 第0位是a,是英文字母,所以从sre中获取字符,当前指针指向d
- 第1位是b,是英文字母,所以从sre中获取字符,当前指针指向c
- 第2位是-,不是英文字母,所以保持不变
- 第3位是c,是英文字母,所以从sre中获取字符,当前指针指向b
- 第4位是d,是英文字母,所以从sre中获取字符,当前指针指向a
综上,结果字符串是"dc-ba"
双指针
看了题解,发现也可以用双指针来解决:
- 指针left和right分别指向s的头和尾
- left向右移动,直到找到第1个英文字母
- right向左移动,直到找到第1个英文字母
- 交换s[left]和s[right]
- 重复2-4步,直到left >= right
Java版本代码
class Solution {
public String reverseOnlyLetters(String s) {
int left = 0;
int right = s.length()-1;
char[] arr = s.toCharArray();
while (left < right) {
while (left < right && !Character.isLetter(arr[left])) {
left++;
}
while (left < right && !Character.isLetter(arr[right])) {
right--;
}
if (left < right) {
char temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
}
return new String(arr);
}
}