题目描述
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
示例 1:
输入: “A man, a plan, a canal: Panama”
输出: true
解释:“amanaplanacanalpanama” 是回文串
示例 2:
输入: “race a car”
输出: false
解释:“raceacar” 不是回文串
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/valid-palindrome
筛选+判断
这里是回文串的检测
1.这里只需要检查大写字母和小写字母还有数字
2.首先建立while循环,确定两个下标i,j之后,分别从前面和后面找到一个数字和字母
3.检查如果i<j那么判断是否相同,若i>=j,则直接退出
//这里一个向后面遍历,一个向前遍历
//如果没有找到的话,返回-1,找到的话,返回对应的下标
//这里有可能找不到,因为字符串如果没有字符和数字的话,那么就找不到
//因为,他是遍历到字符串的中间就结束了,所以,不会出现一边找到,一边没找到的情况
int findNextA(string &s, int index) {
int len = s.size();
for(int i = index; i < len; i++) {
if(isalnum(s[i])) { //判断是否是字母或者数字
return i;
}
}
return -1; //如果没找到,返回-1
}
int findNextB(string &s, int index) {
int len = s.size();
for(int i = index; i >= 0; i--) {
if(isalnum(s[i])) { //判断是否是字母或者数字
return i;
}
}
return -1; //如果没找到,返回-1
}
bool isPalindrome(string s) {
int len = s.size();
int i = 0, j = len - 1;
//当i和j相同,或者当i>j时,还没检查出问题的时候,就证明是回文串
while(i < j) {
//分别从左边开始找到第一个字母和数字的位置
//在从右边找到第一个是字母和数字的位置
i = findNextA(s, i);
j = findNextB(s, j);
//如果两个都不等于-1,那么检查是否相等
if(i != -1 && j != -1) {
if(s[i] - s[j] == 0) { //检查是否完全相等
i++;
j--;
} else if(abs(s[i] - s[j]) == 32 && isalpha(s[i]) && isalpha(s[j])) { //这里如果是字母的话,那么排除大小写
i++;
j--;
} else {
return false;
}
} else if(i == -1 && j == -1) { // 如果都等于-1,那说明这个字符串没有字母
return true;
}
}
return true;
}
/*
i,j的下标一共有这几种情况
1.有字母 { ①有一个字母,i==j,②有两个字母那么i!=j}
2.无字母 {i=-1,j=-1}
这里基本的方法是将原有string中,字符和数字的将其赋值到另一数组中,复制到另一数组中之后,
按照i,j两个指针找到对应的元素比较是否相同即可,当i==j时停止。
或者将字符串逆置,比较这两个字符串是否相等即可。
回文串的特点是,他的逆置还是他自己。*/
bool isPalindrome(string s) {
string temp;
//将数字和字符添加到temp中
//tolower函数的作用将大写转换成小写,而非字符不做处理
//这个函数可以通过ascii判断是否为大写,若为大写那么在将其转为小写
//这样排除了大小写的问题
//for(int i = 0; i < s.size(); i++) {
// if(isalnum(s[i])) {
// temp += tolower(s[i]);
// }
// }
//这里不需要下标for循环可以写成这样
for(char c : s) {
if(isalnum(c)) {
temp += tolower(c);
}
}
string rev_temp(temp.rbegin(), temp.rend()); //以temp字符串逆序的方式创建rev_temp
return rev_temp == temp;
}
时间复杂度是O(|s|),空间复杂度是O(|s|)
bool isPalindrome(string s) {
string temp;
for(char c : s) {
if(isalnum(c)) {
temp += tolower(c);
}
}
for(int i = 0, j = temp.size() - 1; i < j; i++, j--) {
if(temp[i] != temp[j]) {
return false;
}
}
return true;
}
在原字符串上直接判断
先找到对应的字母或者数字,在判断是否相同
bool isPalindrome(string s) {
int i = 0, j = s.size() - 1;
while(i < j) {
//这里条件换成i<j也是可以的,当然,当有字母的时候没差别,没字母的时候i<j比较的次数,稍微少几次。
while(!isalnum(s[i]) && i < s.size()) { //当没有字母的时候,需要检查i的合法性
i++;
}
while(!isalnum(s[j]) && j > 0) {
j--;
}
if(i < j) { //如果i<j,那么一定是找到了字母
if(tolower(s[i]) == tolower(s[j])) { //下标合法,那么比较
i++;
j--;
} else { //如果不相等的话,那么返回false
return false;
}
}//其他情况下,有字母情况下,那么之前对比的都相等,已经到停止条件了
//没有字母的情况下,那么肯定就相等,也到了停止条件了,那么终止
}
return true;
}
int main() {
bool flag = isPalindrome("0P");
cout << flag << endl;
return 0;
}