题记:
如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。
字母和数字都属于字母数字字符。
给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 。
示例 1:
输入: s = “A man, a plan, a canal: Panama”
输出:true
解释:“amanaplanacanalpanama” 是回文串。
示例 2:
输入:s = “race a car”
输出:false
解释:“raceacar” 不是回文串。
示例 3:
输入:s = " "
输出:true
解释:在移除非字母数字字符之后,s 是一个空字符串 “” 。
由于空字符串正着反着读都一样,所以是回文串。
提示:
1 <= s.length <= 2 * 105
s 仅由可打印的 ASCII 字符组成
题目来源:
作者:LeetCode
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xne8id/
来源:力扣(LeetCode)
自己想的方法:
方法一:先转小写拆分为数组,再过滤不符合条件的字符,再利用双指针进行比较
class Solution {
/**
* @param String $s
* @return Boolean
*/
function isPalindrome($s) {
//符合条件的字符
$legal_array = [
0,1,2,3,4,5,6,7,8,9,
"a","b","c","d","e",
"f","g","h","i","j",
"k","l","m","n","o",
"p","q","r","s","t",
"u","v","w","x","y","z"
];
$s_arr = str_split(strtolower($s)); //一概转为小写并划分为数组
foreach($s_arr as $k => $v){
if(!in_array($v,$legal_array)){ //过滤不符合条件的字符串
unset($s_arr[$k]);
}
}
if(count($s_arr) == 0){
return true;
}
$s_arr = array_values($s_arr); //重置下标索引从0开始
//对称比较,如有不等返回false
$letf = 0;
$right = count($s_arr) - 1;
while($letf < $right){
if($s_arr[$letf] != $s_arr[$right]){
return false;
}
$letf++;
$right--;
}
return true;
}
}
$s = "A man, a plan, a canal: Panama";
$solution = new Solution();
$result = $solution->isPalindrome($s);
var_dump($result);
/**
输出结果为:bool(true)
*/
方法二:先正则过滤掉不符合条件的字符并转小写,再反转处理后的字符串,最后判断反转前后的字符串是否相等
class Solution {
/**
* @param String $s
* @return Boolean
*/
function isPalindrome($s) {
//过滤非字母数字字符并转小写
$leagal_str = strtolower(preg_replace('/[^a-z0-9]/i','',$s));
//反转处理后的字符串
$rev_str = strrev($leagal_str);
//相等则为true否则为false
if($leagal_str != $rev_str){
return false;
}
return true;
}
}
$s = "A man, a plan, a canal: Panama";
$solution = new Solution();
$result = $solution->isPalindrome($s);
var_dump($result);
/**
输出结果为:bool(true)
*/
方法三:与方法一差不多,先正则处理不符合条件的字符,拆分为数组,再比较对称
class Solution {
/**
* @param String $s
* @return Boolean
*/
function isPalindrome($s) {
//过滤非字母数字字符并转小写
$leagal_str = strtolower(preg_replace('/[^a-z0-9]/i','',$s));
if(strlen($leagal_str) == 0){
return true;
}
//拆分为数组
$leagal_str_array = str_split($leagal_str);
//对称比较
$left = 0;
$right = count($leagal_str_array) - 1;
while($left < $right){
if($leagal_str_array[$left] != $leagal_str_array[$right]){
return false;
}
$left++;
$right--;
}
return true;
}
}
$s = "A man, a plan, a canal: Panama";
$solution = new Solution();
$result = $solution->isPalindrome($s);
var_dump($result);
/**
输出结果为:bool(true)
*/
官方解题方法:(与自己想的方法大体是差不多的)
一:双指针解决
这题没什么难度,最简单的就是使用双指针,一个指向前,一个指向后,遇到空格以及特殊字符要跳过,然后判断,画个图来看下
public boolean isPalindrome(String s) {
if (s.length() == 0)
return true;
int left = 0, right = s.length() - 1;
while (left < right) {
//因为题中说了,只考虑字母和数字,所以不是字母和数字的先过滤掉
while (left < right && !Character.isLetterOrDigit(s.charAt(left)))
left++;
while (left < right && !Character.isLetterOrDigit(s.charAt(right)))
right--;
//然后把两个字符变为小写,在判断是否一样,如果不一样,直接返回false
if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right)))
return false;
left++;
right--;
}
return true;
}
二:双指针的另一种写法
我们还可以在比较之前字母全部转化为小写,这里改为for循环的方式,只不过是换汤不换药,原理还都是一样的
public boolean isPalindrome(String s) {
if (s == null || s.length() == 0)
return true;
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;
}
三:使用正则匹配
这题还可以使用正则匹配,把特殊字符过滤掉,只留下字母和数字,然后转化为小写,再反转,最后在判断是否相等。
public boolean isPalindrome(String s) {
String actual = s.replaceAll("[^A-Za-z0-9]", "").toLowerCase();
String rev = new StringBuffer(actual).reverse().toString();
return actual.equals(rev);
}
四:递归方式实现
如果想玩出花样,我们还可以把第一种的解题思路改为递归的方式
public boolean isPalindrome(String s) {
return isPalindromeHelper(s, 0, s.length() - 1);
}
public boolean isPalindromeHelper(String s, int left, int right) {
if (left >= right)
return true;
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);
}
官方解题来源:
作者:数据结构和算法
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xne8id/?discussion=BHK3ga
来源:力扣(LeetCode)