「这是我参与11月更文挑战的第 11 天,活动详情查看:2021最后一次更文挑战」
原题链接
917. 仅仅反转字母 - 力扣(LeetCode) (leetcode-cn.com)
题目描述
给定一个字符串 S,返回 “反转后的” 字符串,其中不是字母的字符都保留在原地,而所有字母的位置发生反转。
测试用例
示例 1:
输入:"ab-cd"
输出:"dc-ba"
示例 2:
输入:"a-bC-dEf-ghIj"
输出:"j-Ih-gfE-dCba"
示例 3:
输入:"Test1ng-Leet=code-Q!"
输出:"Qedo1ct-eeLg=ntse-T!"
参数限制
S.length <= 10033 <= S[i].ASCIIcode <= 122S中不包含 `` or"
分析
对于这种在原数组上直接做替换的操作,直接双指针安排
pl 从 0 开始往右移,找到字母后停止;pr 往左移,找到字母后停止;然后交换 pl, pr 指针对应的字母,然后重复上述步骤,直到 pl>pr 终止循环操作。这个时候返回的字符串就是答案
至于如何判断当前指向的元素是否为字符,直接使用正则表达式 /[a-zA-Z]/ 来匹配即可
代码
var reverseOnlyLetters = function(s) {
s = s.split('')
let l = 0,
r = s.length - 1;
let reg = /[a-zA-Z]/
for (;;) {
while (!reg.test(s[l])) {
l++;
}
while (!reg.test(s[r])) {
r--;
}
if (l >= r) break;
let c = s[l];
s[l++] = s[r];
s[r--] = c;
}
return s.join('')
};
虽然是 for 嵌套 while 的风格,但实际上也只是遍历了一次数组,仅仅是阅读起来会有点吃力
优化
由于字符串的比较是使用的正则,担心这里面会有一些性能的损耗,我们直接替换为 ascll码 的比较
控制台查阅资料可以知道 [a, z] = [97, 122], [A, Z] = [65, 90]
同时优化一下 for 中嵌套 while 的风格
var reverseOnlyLetters = function(s) {
s = s.split('')
let l = 0,
r = s.length - 1;
for (; l < r;) {
if (!check(s[l])) {
l++;
continue;
}
if (!check(s[r])) {
r--;
continue;
}
let c = s[l];
s[l++] = s[r];
s[r--] = c;
}
return s.join('');
function check(s) {
let c = s.charCodeAt();
return (c >= 65 && c <= 90) || (c >= 97 && c <= 122);
}
};
今天的力扣刷题就分享到这里,感谢大家的阅读~