一、题目描述
如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。
字母和数字都属于字母数字字符。
给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 。
二、测试用例
示例 1:
cpp
输入: s = "A man, a plan, a canal: Panama"
输出:true
解释:"amanaplanacanalpanama" 是回文串。
示例 2:
cpp
输入:s = "race a car"
输出:false
解释:"raceacar" 不是回文串。
示例 3:
cpp
输入:s = " "
输出:true
解释:在移除非字母数字字符之后,s 是一个空字符串 "" 。
由于空字符串正着反着读都一样,所以是回文串。
提示:
cpp
1 <= s.length <= 2 * 105
s 仅由可打印的 ASCII 字符组成
三、解题思路
- 基本思路:
头指针+尾指针,一直判断是否相等,直到两指针相遇或者字符不相等停止 - 具体思路:
- 预处理:定义
trim(string& s)
函数,功能是删除非字母或数字的字符,并且字符转小写。使用双指针实现,i
指针用于保存字符,j
指针用于遍历,遇到要保持的就赋值给i
指针,最后删除多余字符。 - 双指针遍历:先使用
trim
函数处理字符串;因为回文串中心对称,所以我们从两端开始一直判断是否相同。定义头指针i
和尾指针j
,初始化为0
和n-1
。判断两指针所指字符是否相同,相同就继续判断下一个,i++
和j--
。不同则表示不是回文串,返回false
。直到两指针相遇都相同,则表示是回文串,返回true
。
- 预处理:定义
四、参考代码
时间复杂度: O ( n ) \Omicron(n) O(n)
空间复杂度: O ( 1 ) \Omicron(1) O(1)
cpp
class Solution {
public:
void trim(string& s) {
int n = s.length();
int i = 0, j = 0;
while (j < n) {
s[j] = tolower(s[j]);
if (isalnum(s[j])) {
s[i++] = s[j++];
} else {
j++;
}
}
s.erase(i, n - i);
}
bool isPalindrome(string s) {
trim(s);
int n = s.length();
for (int i = 0, j = n - 1; i < j; i++, j--) {
if (s[i] != s[j]) {
return false;
}
}
return true;
}
};