leetcode - [125] 验证回文串|刷题打卡
我是通过idea的leetcode插件获取题目做题的,所以题目描述基本都会有注释符号哈
1. 题目描述
* // [125] 验证回文串
* // 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
* //
* // 说明:本题中,我们将空字符串定义为有效的回文串。
* //
* // 示例 1:
* //
* // 输入: "A man, a plan, a canal: Panama"
* //输出: true
* //
* //
* // 示例 2:
* //
* // 输入: "race a car"
* //输出: false
* //
* // Related Topics 双指针 字符串
2. 思路分析
这道题目看到跟之前的[9] 回文数类似,使用 双指针 ,对照前后,如果全部符合,返回true,中间有不匹配的,返回false
区别主要在于可能存在 非数字、非字母的内容需要跳过,主要在于这部分的实现。
下面的代码用了两种方式:
1. Character.isLetterOrDigit() 方法(PS:这个方法会将中文也当成字母,即Letter)
2. 手动实现
3. AC代码
public class No125 {
public boolean isPalindrome(String s) {
return method1(s);
// return method2(s);
}
/**
* 解析为小写字符数组
* 调用 JDK Character 自带 isLetterOrDigit方法来判断是否落在 字母和数字范围(注意:isLetterOrDigit 会把中文当成是字符)
*
* @param s
* @return
*/
private boolean method1(String s) {
s = s.toLowerCase();
char[] c = s.toCharArray();
int l = 0;
int r = s.length()-1;
// 左边的指针还小于右边的就继续进行校验判断,会慢慢往中间靠近
while(l < r) {
if(!isLetterOrDigit(c[l])) {
l++;
} else if(!isLetterOrDigit(c[r])) {
r--;
} else if(c[l++] != c[r--]) {
return false;
}
}
return true;
}
/**
* Character的方法,copy过来了
* 这方面还不是特别懂,我理解是把 对应 Letter 和数字范围的字符 取并集
*
* 相关链接:https://www.compart.com/en/unicode/category
* @param codePoint
* @return
*/
public static boolean isLetterOrDigit(int codePoint) {
return (
(
(
// 赋值 对应Letter 的值,取并集
(1 << Character.UPPERCASE_LETTER) |
(1 << Character.LOWERCASE_LETTER) |
(1 << Character.TITLECASE_LETTER) |
(1 << Character.MODIFIER_LETTER) |
(1 << Character.OTHER_LETTER) |
(1 << Character.DECIMAL_DIGIT_NUMBER)
// 跟对应字符的
) >> Character.getType(codePoint)
) & 1 ) != 0;
}
/**
* 来自 leetCode 解答 [手写版本无函数调用]
*
* 主要是封装了两个方法, isOK 和 equal
* isOK - 字符落在字母以及数字范围内
* equal - 忽略大小写
*
* 执行耗时:3 ms,击败了92.60% 的Java用户
* 内存消耗:38.5 MB,击败了70.62% 的Java用户
*
* @param s
* @return
*/
public boolean method2(String s) {
int i=0,j=s.length()-1;
while(i<j){
char a=s.charAt(i),b=s.charAt(j);
if(isOK(a)&&isOK(b)&&!equal(a,b))return false;
if(!isOK(a)&&i<j){i++;continue;}
if(!isOK(b)&&i<j){j--;continue;}
if(equal(a,b)&&i<j){i++;j--;continue;}
if(!equal(a,b)&&i<j)return false;
i++;j--;
}
return i>=j;
}
/**
* 忽略大小写的限制
*
* @param a
* @param b
* @return
*/
public boolean equal(char a,char b){
if('a'<=a&&a<='z')a-='a';
if('A'<=a&&a<='Z')a-='A';
if('a'<=b&&b<='z')b-='a';
if('A'<=b&&b<='Z')b-='A';
return a==b;
}
/**
* 字母或者数字
*
* @param c
* @return
*/
public boolean isOK(char c){
return ('a'<=c&&c<='z')||('A'<=c&&c<='Z')||('0'<=c&&c<='9');
}
}
4. 总结
一点点感想,无论是做题还是做项目,实现功能的时候经常会需要很多工具类的帮助,以至于经常会自己封装很多工具类。其实可能很多功能都在引入的依赖中可能就包含了,或者JDK自带了,可以稍微留意一下,避免代码重复,保持代码整洁。
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情