一句话概要
双指针从两端同时向中心遍历,不一致则返回false。
题目
给定一个字符串 s
,验证 s
是否是 回文串 ,只考虑字母和数字字符,可以忽略字母的大小写。
本题中,将空字符串定义为有效的 回文串 。
思路
我们需要忽略掉除了字母和数字以外的字符。
可以先遍历字符串的每一个字符,先做一次预处理。预处理需要移除掉非数字字母的字符,之后将大写字母统一成小写。
之后用两个指针从两侧开始向中心遍历,比对两个指针对应的元素是否一致。
这里涉及到了ASCII编码,可以参考剑指 Offer II 002. 二进制加法这一题的扩展知识。
解法一:预处理字符串,双指针向中心遍历
代码
public boolean isPalindrome(String s) {
StringBuilder sb = new StringBuilder();
for (char c : s.toCharArray()) {
if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
sb.append(c);
}
}
String finalStr = sb.toString().toLowerCase();
if ("".equals(finalStr)) {
return true;
}
for (int i = 0; i <= finalStr.length() / 2 - 1; i++) {
if (finalStr.charAt(i) != finalStr.charAt(finalStr.length() - i - 1)) {
return false;
}
}
return true;
}
解法二:直接双指针向中心遍历
逻辑
对于第一个解法,完全可以直接就开始双指针向中心遍历,省去一次预处理的过程,在遍历的同时,去判断是否为数字或者字母。
代码
public boolean isPalindrome(String s) {
String s1 = s.toLowerCase();
int left = 0;
int right = s1.length() - 1;
while (left < right) {
char leftC = s1.charAt(left);
char rightC = s1.charAt(right);
if (needRemove(leftC)) {
left++;
continue;
}
if (needRemove(rightC)) {
right--;
continue;
}
if (leftC != rightC) {
return false;
}
left++;
right--;
}
return true;
}
public boolean needRemove(char c){
return (c < '0' || c > '9') && (c < 'a' || c > 'z');
}