题目描述
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
示例
示例 1:
输入: "A man, a plan, a canal: Panama"
输出: true
解释:"amanaplanacanalpanama" 是回文串
示例 2:
输入: "race a car"
输出: false
解释:"raceacar" 不是回文串
提示:
1 <= s.length <= 2 * 105
字符串 s 由 ASCII 字符组成
来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/va…
分析
- 根据题目描述,只考虑字母和数字,因此第一步首先将字符串转换成只包含数字和字母的形式
- 要找回文字符串,就是第一个字符和最后一个字符相同,第二个字符和倒数第二个字符相同,依次类推,我们可以想到用双指针法,left指针指向首字符,right指针指向尾字符,又根据题目描述忽略大小写,因此我们将字符统一转换成小写进行比较,如果tolower(s[left]) == tolower(s[right]),那么说明left位置和right位置的字符组成回文,比较下一对,left++,right++,依次比较,直到left和right相遇或者遇到不满足回文条件(left和right位置的字符不相同)时退出
例:s="race a car"
- 经过处理,将其转换为只包含数字和字母的形式"raceacar",一共8个字符(0~7)
- left=0,right=7,tolower(s[left])==r,tolower(s[right])==r,相同,符合回文条件,left++,right--,比较两个值都为a,符合,依次类推,直到left==3,right==4时,tolower(s[left])==e,tolower(s[right])==a,不相等,因此该字符串不符合回文条件
实现
void updateString(char *s, char *pRes, int *pResLen)
{
while (*s != '\0') {
if (((*s - '0') >= 0 && (*s - '0') <= 9) || (*s >= 'a' && *s <= 'z') ||
(*s >= 'A' && *s <= 'Z')) { // 表明字符是数字或字母,放入pRes中
*pRes = *s;
pRes++;
(*pResLen)++;
}
s++;
}
}
bool isPalindrome(char *s)
{
int resLen = 0; // 保存源字符串中去掉非字母与非数字的字符串长度
// pRes指针后面指向源字符串中去掉非字母与非数字的字符串
char *pRes = (char*)malloc(sizeof(char) * strlen(s));
if (strlen(s) <= 1) { // 如果字符串为空或者只有一个字符,认为是回文字符串
return true;
}
// 给pRes和pResLen赋值
updateString(s, pRes, &resLen);
if (resLen <= 1) {
return true;
}
// left和right分别指向字符串两边,向中间夹逼,判断是否回文
int left = 0;
int right = resLen - 1;
while (left < right) {
if (tolower(pRes[left]) != tolower(pRes[right])) { // 不是回文
return false;
}
left++;
right--;
}
return true;
}