题干
原题链接:https://leetcode-cn.com/problems/valid-palindrome/
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
示例 1:
输入: "A man, a plan, a canal: Panama"
输出: true
示例 2:
输入: "race a car"
输出: false
注:
“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串
思路
本题有两种解法,一种是从中间到两边去验证(中心扩散法),一种是从两边趋向中间去验证(双指针法),这里讨论第二种解法。
主体思路是设定两个指针,一个在头,一个在尾,验证头尾指针的字符是否相等,若不等,则不是回文串,否则继续验证,直到俩指针在中间相遇。
主体代码入下:
int len = s.length();
int i = 0;
int j = len -1;
while(i<j){
if(s.charAt(i) != s.charAt(j)){
return false;
}
i++;
j--;
}
return true;
又,本题题干只考虑字母和数字字符,且可以忽略字母的大小写,需要额外做两个步骤。
一是将所有字符串转换为全小写(或全大写)
s = s.toLowerCase();
二是在指针移动时判断该指针所在位置的字符串是否是字母或数字,如果不是,则指针后(前)移,直到是为止。
while(!isAlphanumeric(s.charAt(i))){
i++;
}
while(!isAlphanumeric(s.charAt(j))){
j--;
}
private boolean isAlphanumeric(char c) {
if ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9') {
return true;
}
return false;
}
这里还要考虑一种特殊情况,就是所有字符都是非法字符,如“*&^% !# ”,上面代码执行时,i会一直增加直到等于len,引发数组越界,所以我们需要额外做一个判断:
while(!isAlphanumeric(s.charAt(i))){
i++;
if(i == len){
return true;
}
}
代码
完整代码如下:
public class IsPalindrome {
public boolean isPalindrome(String s) {
int len = s.length();
s =s.toLowerCase();
int i = 0;
int j = len -1;
while(i<j) {
while(!isAlphanumeric(s.charAt(i))) {
i++;
if(i == len) {
return true;
}
}
while(!isAlphanumeric(s.charAt(j))) {
j--;
}
if(s.charAt(i) != s.charAt(j)) {
return false;
}
i++;
j--;
}
return true;
}
private boolean isAlphanumeric(char c) {
if ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9') {
return true;
}
return false;
}
}