学习目标:
本次学习目标为 力扣初级算法-字符串,其中主要的LC如下:
- 验证回文串
学习内容:
- 验证回文串 -----(链接)
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。示例1:
输入: “A man, a plan, a canal: Panama”
输出: true
解释:“amanaplanacanalpanama” 是回文串示例2:
输入: “race a car”
输出: false
解释:“raceacar” 不是回文串说明: 1 <= s.length <= 2 * 105
字符串 s 由 ASCII 字符组成
解题思路:
- 解法一:双指针法
- 边界问题:
- 入参字符字符大小写问题,可直接转换为小写
- 入参字符存在非字母和数组
- 代码逻辑过程:
- 将字符串转化为字符数组
- 终止条件: 左指针大于右指针 (最开始的想法是左、右指针不相等,但实际是超过相等之后就会存在问题)
- 定位当前循环左指针的下标----条件是 左指针的元素时数组或者是字母,但任然有一个大前提就是 左指针不能超过右指针
- 定位当前循环右指针的下标----条件是 右指针的元素时数组或者是字母,前提是 右指针大于左指针
- 比较前后两指针的元素,元素不相等则直接 return false – 此处注意转换为 小写字母后再比较
- 代码实现:
// 解法一: 双指针
public static boolean isPalindrome01(String s) {
// 边界问题
if (null == s || s.length() == 0) {
return false;
}
// 将字符串转化为字符数组
char[] chars = s.toCharArray();
int left = 0;
int right = s.length() - 1;
// 终止条件: 左指针大于右指针 (最开始的想法是左、右指针不相等,但实际是超过相等之后就会存在问题)
while (left < right) {
// 定位当前循环左指针的下标----条件是 左指针的元素时数组或者是字母,但任然有一个大前提就是 左指针不能超过右指针
while (left < right && !Character.isLetterOrDigit(chars[left])) {
left++;
}
// 定位当前循环右指针的下标----条件是 右指针的元素时数组或者是字母,前提是 右指针大于左指针
while (right > left && !Character.isLetterOrDigit(chars[right])) {
right--;
}
// 比较前后两指针的元素,元素不相等则直接 return false -- 此处注意转换为 小写字母后再比较
if (Character.toLowerCase(chars[left]) != Character.toLowerCase(chars[right])) {
return false;
}
left++;
right--;
}
return true;
}
- 解法二:基于解法一下先将字符串统一转为小写字符
- 边界问题:
- 入参字符字符大小写问题,可直接转换为小写
- 入参字符存在非字母和数组
- 代码逻辑过程:
- 将字母转换为小写
- 将原先的 while 循环,改写为 for循环
- 定位左、右指针逻辑与解法一一致
- 代码实现:
// 解法二: 基于解法一下先将字符串统一转为小写字符
public boolean isPalindrome02(String s) {
// 边界问题
if (null == s || s.length() == 0) {
return false;
}
// 将字母转换为小写
s = s.toLowerCase();
for (int i = 0, j = s.length() - 1; i < j; i++, j--) {
while (i < j && !Character.isLetterOrDigit(s.charAt(i))) {
i++;
}
while (i < j && !Character.isLetterOrDigit(s.charAt(j))) {
j--;
}
if (s.charAt(i) != s.charAt(j)) {
return false;
}
}
return true;
}
- 解法三:正则表达式
- 边界问题:
- 入参字符字符大小写问题,可直接转换为小写
- 入参字符存在非字母和数组
- 代码逻辑过程:
- 使用正则直接替换非字母和数字的字符,命名为 actual
- 将字符串string 转为 StringBuilder ,再将其倒置 reverse 为 reverseOfS
- 比较 actual 与 reverseOfS
- 代码实现:
public boolean isPalindrome03(String s) {
// 边界问题
if (null == s || s.length() == 0) {
return false;
}
// 使用正则直接替换非字母和数字的字符
String actual = s.replaceAll("[^A-Za-z0-9]", "").toLowerCase();
// 将字符串 reverse
String reverseOfS = new StringBuilder(actual).reverse().toString();
return actual.equals(reverseOfS);
}
- 解法四:递归写法
- 边界问题:
- 入参字符字符大小写问题,可直接转换为小写
- 入参字符存在非字母和数组
- 代码逻辑过程:
- 将解法一种的 while 循环改写为 递归,此处需要注意递归终止条件。
// 解法四: 递归写法
public boolean isPalindrome04(String s) {
// 边界问题
if (null == s || s.length() == 0) {
return false;
}
// 递归终止条件
return isPalindromeHelper(s, 0, s.length() - 1);
}
public boolean isPalindromeHelper(String s, int left, int right) {
if (left > right) {
return false;
}
while (left < right && !Character.isLetterOrDigit(s.charAt(left)))
left++;
while (left < right && !Character.isLetterOrDigit(s.charAt(right)))
right--;
return Character.toLowerCase(s.charAt(left)) == Character.toLowerCase(s.charAt(right)) && isPalindromeHelper(s, ++left, --right);
}
学习笔记:
- 什么是回文串
“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。