1 题目描述
1.1 英文描述
Given a string s, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.
Example 1:
Input: "A man, a plan, a canal: Panama"
Output: true
Example 2:
Input: "race a car"
Output: false
Constraints:
1)1 <= s.length <= 2 * 105
2)s consists only of printable ASCII characters.
1.2 中文描述
给你一个字符串,你要判断它是否是回文字符串,字符串只考虑字母和数字,其他的字符可以忽略。 另外,对于字母,可以忽略大小写。
2.解法
2.1 解法1 - 翻转字符串
将字符串翻转后和原字符串进行比较。
/**
* 方式1:翻转字符串
*/
public static boolean valindPalindrome(String str){
//去掉非字母和数字的字符
String str1 = str.replaceAll("[^a-zA-Z0-9]", "");
//字母全转为小写
String str2 = str1.toLowerCase();
//翻转字符串
String str3 = new StringBuilder(str2).reverse().toString();
//对比翻转前与翻转后的字符是否相等
return str2.equals(str3);
}
2.2 解法2 - 翻转字符串(代码优化)
也是将字符串翻转后和原字符串进行比较,不过这是对代码进行了优化,一行代码解决问题。
/**
* 方式2:翻转字符串(一行代码)
*/
public static boolean valindPalindrome2(String str){
return str.replaceAll("[^a-zA-Z0-9]","")
.equalsIgnoreCase(
new StringBuilder(str.replaceAll("[^a-zA-Z0-9]","")).reverse().toString()
);
}
2.3 解法3 - 双指针
使用双指针解决问题。首指针从头向尾遍历,尾指针从尾向头遍历,遍历的过程逐个比较。
/**
* 方式3:双指针
* 首指针从头向尾遍历,尾指针从尾向头遍历。
* 遍历的过程逐个比较。
*/
public static boolean valindPalindrome3(String str){
//初始化头指针和尾指针
int p1 = 0;
int p2 = str.length() - 1;
//循环遍历比较
while (p1 < p2){
//取出首指针对应的值
char c1 = str.charAt(p1);
//如果不是字母和数字则跳过,取下一个值
while (!isDigital(c1) && !isLetter(c1) && p1 < p2){
p1++;
c1 = str.charAt(p1);
}
//取出尾指针对应的值
char c2 = str.charAt(p2);
//如果不是字母和数字则跳过,取下一个值
while (!isDigital(c2) && !isLetter(c2) && p1 < p2){
p2--;
c2 = str.charAt(p2);
}
//忽略大小写之后比较首指针和尾指针对应的值
//如果不相等则说明不是回文字符串
//如果相等则p1++, p2--之后,进行下一轮比较
if(!String.valueOf(c1).equalsIgnoreCase(String.valueOf(c2))){
return false;
}else {
p1++;
p2--;
}
}
//跳出循环这说明肯定是回文字符串
return true;
}
/**
* 判断是否为数字
*/
public static boolean isDigital(char c){
return c >= '0' && c <= '9';
}
/**
* 判断是否为字母
*/
public static boolean isLetter(char c){
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
2.4 解法4 - 双指针(代码优化)
使用双指针解决问题。首指针从头向尾遍历,尾指针从尾向头遍历,遍历的过程逐个比较。
不过这个解法对代码进行了优化。
/**
* 方式4:双指针(代码优化)
* 首指针从头向尾遍历,尾指针从尾向头遍历。
* 遍历的过程逐个比较。
*/
public static boolean valindPalindrome4(String str){
//初始化头指针和尾指针
int head = 0;
int tail = str.length() - 1;
//循环遍历比较
while (head < tail){
//取出首指针对应的值
char cHead = str.charAt(head);
//取出尾指针对应的值
char cTail = str.charAt(tail);
//如果c1不是字母或数字,则p++之后进入下一轮循环
if(!Character.isLetterOrDigit(cHead)){
head++;
}else if(!Character.isLetterOrDigit(cTail)){
//如果c2不是字母或数字,则p++之后进入下一轮循环
tail--;
}else if(!String.valueOf(cHead).equalsIgnoreCase(String.valueOf(cTail))){
//如果c1和c2都是字母或者数字,则忽略大小写之后进行比较,如果不相等则不是回文字符串
return false;
}else {
//如果c1和c2都是字母或数字,并且c1等于c2,则p1++;p2--;之后进行下一轮循环
head++;
tail--;
}
}
//跳出循环这说明肯定是回文字符串
return true;
}
欢迎关注个人公众号,可直接扫描以下二维码或微信搜索“阿毛聊技术”进行关注。